Skip to content
This repository has been archived by the owner on May 11, 2022. It is now read-only.

Extract service implementation #2

Merged
merged 8 commits into from
Oct 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .gx/lastpubver
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.0: QmNtEW59XTrreF9U4NAjYUmixEJ56HnfiJCj1p97bFnah2
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ It allows peers to figure out their NAT dialability situation by using test dial

## Documenation

See https://godoc.org/github.com/libp2p/go-libp2p-discovery.
See https://godoc.org/github.com/libp2p/go-libp2p-autonat

## Contribute

Expand Down
70 changes: 0 additions & 70 deletions addr.go

This file was deleted.

20 changes: 14 additions & 6 deletions autonat.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type AmbientAutoNAT struct {
ctx context.Context
host host.Host

getAddrs GetAddrs

mx sync.Mutex
peers map[peer.ID]struct{}
status NATStatus
Expand All @@ -61,12 +63,18 @@ type AmbientAutoNAT struct {
}

// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host
func NewAutoNAT(ctx context.Context, h host.Host) AutoNAT {
// If getAddrs is nil, h.Addrs will be used
func NewAutoNAT(ctx context.Context, h host.Host, getAddrs GetAddrs) AutoNAT {
if getAddrs == nil {
getAddrs = h.Addrs
}

as := &AmbientAutoNAT{
ctx: ctx,
host: h,
peers: make(map[peer.ID]struct{}),
status: NATStatusUnknown,
ctx: ctx,
host: h,
getAddrs: getAddrs,
peers: make(map[peer.ID]struct{}),
status: NATStatusUnknown,
}

h.Network().Notify(as)
Expand Down Expand Up @@ -123,7 +131,7 @@ func (as *AmbientAutoNAT) autodetect() {
return
}

cli := NewAutoNATClient(as.host)
cli := NewAutoNATClient(as.host, as.getAddrs)
failures := 0

for _, p := range peers {
Expand Down
87 changes: 70 additions & 17 deletions autonat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package autonat

import (
"context"
"net"
"testing"
"time"

libp2p "github.com/libp2p/go-libp2p"
pb "github.com/libp2p/go-libp2p-autonat/pb"

ggio "github.com/gogo/protobuf/io"
bhost "github.com/libp2p/go-libp2p-blankhost"
host "github.com/libp2p/go-libp2p-host"
inet "github.com/libp2p/go-libp2p-net"
pstore "github.com/libp2p/go-libp2p-peerstore"
swarmt "github.com/libp2p/go-libp2p-swarm/testing"
ma "github.com/multiformats/go-multiaddr"
)

func init() {
Expand All @@ -17,24 +23,76 @@ func init() {
AutoNATIdentifyDelay = 100 * time.Millisecond
}

func makeAutoNAT(ctx context.Context, t *testing.T) (host.Host, AutoNAT) {
h, err := libp2p.New(ctx, libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
if err != nil {
t.Fatal(err)
// these are mock service implementations for testing
func makeAutoNATServicePrivate(ctx context.Context, t *testing.T) host.Host {
h := bhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
h.SetStreamHandler(AutoNATProto, sayAutoNATPrivate)
return h
}

func makeAutoNATServicePublic(ctx context.Context, t *testing.T) host.Host {
h := bhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
h.SetStreamHandler(AutoNATProto, sayAutoNATPublic)
return h
}

func sayAutoNATPrivate(s inet.Stream) {
defer s.Close()
w := ggio.NewDelimitedWriter(s)
res := pb.Message{
Type: pb.Message_DIAL_RESPONSE.Enum(),
DialResponse: newDialResponseError(pb.Message_E_DIAL_ERROR, "no dialable addresses"),
}
w.WriteMsg(&res)
}

func sayAutoNATPublic(s inet.Stream) {
defer s.Close()
w := ggio.NewDelimitedWriter(s)
res := pb.Message{
Type: pb.Message_DIAL_RESPONSE.Enum(),
DialResponse: newDialResponseOK(s.Conn().RemoteMultiaddr()),
}
w.WriteMsg(&res)
}

a := NewAutoNAT(ctx, h)
func newDialResponseOK(addr ma.Multiaddr) *pb.Message_DialResponse {
dr := new(pb.Message_DialResponse)
dr.Status = pb.Message_OK.Enum()
dr.Addr = addr.Bytes()
return dr
}

func newDialResponseError(status pb.Message_ResponseStatus, text string) *pb.Message_DialResponse {
dr := new(pb.Message_DialResponse)
dr.Status = status.Enum()
dr.StatusText = &text
return dr
}

func makeAutoNAT(ctx context.Context, t *testing.T, ash host.Host) (host.Host, AutoNAT) {
h := bhost.NewBlankHost(swarmt.GenSwarm(t, ctx))
a := NewAutoNAT(ctx, h, nil)
a.(*AmbientAutoNAT).peers[ash.ID()] = struct{}{}

return h, a
}

// Note: these tests assume the host has only private inet addresses!
func connect(t *testing.T, a, b host.Host) {
pinfo := pstore.PeerInfo{ID: a.ID(), Addrs: a.Addrs()}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should move the PeerInfo struct to somewhere more common. It's a pity to have to import peerstore as a client, even if you don't intend to use the peerstore itself.

Added a note about this: https://github.com/libp2p/go-libp2p-peerstore/issues/35.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this gets to me every single time as peerstore is a pretty big dependency.
Maybe we should have it in go-libp2p-peer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I think host is a better place as peer doesn't depend on multiaddrs. Noted for the (hopefully near) future.

err := b.Connect(context.Background(), pinfo)
if err != nil {
t.Fatal(err)
}
}

// tests
func TestAutoNATPrivate(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

hs, _ := makeAutoNATService(ctx, t)
hc, an := makeAutoNAT(ctx, t)
hs := makeAutoNATServicePrivate(ctx, t)
hc, an := makeAutoNAT(ctx, t, hs)

status := an.Status()
if status != NATStatusUnknown {
Expand All @@ -54,11 +112,8 @@ func TestAutoNATPublic(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

save := private4
private4 = []*net.IPNet{}

hs, _ := makeAutoNATService(ctx, t)
hc, an := makeAutoNAT(ctx, t)
hs := makeAutoNATServicePublic(ctx, t)
hc, an := makeAutoNAT(ctx, t, hs)

status := an.Status()
if status != NATStatusUnknown {
Expand All @@ -72,6 +127,4 @@ func TestAutoNATPublic(t *testing.T) {
if status != NATStatusPublic {
t.Fatalf("unexpected NAT status: %d", status)
}

private4 = save
}
16 changes: 12 additions & 4 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,21 @@ type AutoNATError struct {
Text string
}

// GetAddrs is a function that returns the addresses to dial back
type GetAddrs func() []ma.Multiaddr

// NewAutoNATClient creates a fresh instance of an AutoNATClient
func NewAutoNATClient(h host.Host) AutoNATClient {
return &client{h: h}
// If getAddrs is nil, h.Addrs will be used
func NewAutoNATClient(h host.Host, getAddrs GetAddrs) AutoNATClient {
if getAddrs == nil {
getAddrs = h.Addrs
}
return &client{h: h, getAddrs: getAddrs}
}

type client struct {
h host.Host
h host.Host
getAddrs GetAddrs
}

func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error) {
Expand All @@ -46,7 +54,7 @@ func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error)
r := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
w := ggio.NewDelimitedWriter(s)

req := newDialMessage(pstore.PeerInfo{ID: c.h.ID(), Addrs: c.h.Addrs()})
req := newDialMessage(pstore.PeerInfo{ID: c.h.ID(), Addrs: c.getAddrs()})
err = w.WriteMsg(req)
if err != nil {
return nil, err
Expand Down
55 changes: 51 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,63 @@
"gxDependencies": [
{
"author": "whyrusleeping",
"hash": "QmPL3AKtiaQyYpchZceXBZhZ3MSnoGqJvLZrc7fzDTTQdJ",
"name": "go-libp2p",
"version": "6.0.19"
"hash": "QmYWXhT9R7Q5wuBXAkdKqd8aYZwijB7KvWSZFY7SGfnoaw",
"name": "go-libp2p-host",
"version": "3.0.14"
},
{
"author": "whyrusleeping",
"hash": "QmaNMjwCgftJwZHVUJU24ySvPMFeEnHzVnnmCpNsKZguTB",
"name": "go-libp2p-net",
"version": "3.0.14"
},
{
"author": "whyrusleeping",
"hash": "QmTRhk7cgjUf2gfQ3p2M9KPECNZEW9XUrmHcFCgog4cPgB",
"name": "go-libp2p-peer",
"version": "2.4.0"
},
{
"author": "whyrusleeping",
"hash": "QmatE2nxsAaK96jxMFBPMtVJEsaMrcJ21UYBHpXTkEM95r",
"name": "go-libp2p-peerstore",
"version": "2.0.5"
},
{
"hash": "QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae",
"name": "go-log",
"version": "1.5.7"
},
{
"author": "whyrusleeping",
"hash": "QmTexoZajNmyWoxHMt2gCu9TAzfhV22LGrf4h7vmZXkWre",
"name": "go-libp2p-blankhost",
"version": "0.3.14"
},
{
"author": "whyrusleeping",
"hash": "QmQ23JpVSdm2G3e2x4TFNSApeZ16rsw7unM42s5TENgBep",
"name": "go-libp2p-swarm",
"version": "3.0.20"
},
{
"author": "whyrusleeping",
"hash": "QmdxUuburamoF6zF9qjeQC4WYcWGbWuRmdLacMEsW8ioD8",
"name": "gogo-protobuf",
"version": "0.0.0"
},
{
"author": "multiformats",
"hash": "QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7",
"name": "go-multiaddr",
"version": "1.3.0"
}
],
"gxVersion": "0.12.1",
"language": "go",
"license": "",
"name": "go-libp2p-autonat",
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
"version": "0.0.0"
"version": "1.0.0"
}

15 changes: 0 additions & 15 deletions proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

logging "github.com/ipfs/go-log"
pstore "github.com/libp2p/go-libp2p-peerstore"
ma "github.com/multiformats/go-multiaddr"
)

const AutoNATProto = "/libp2p/autonat/1.0.0"
Expand All @@ -25,17 +24,3 @@ func newDialMessage(pi pstore.PeerInfo) *pb.Message {

return msg
}

func newDialResponseOK(addr ma.Multiaddr) *pb.Message_DialResponse {
dr := new(pb.Message_DialResponse)
dr.Status = pb.Message_OK.Enum()
dr.Addr = addr.Bytes()
return dr
}

func newDialResponseError(status pb.Message_ResponseStatus, text string) *pb.Message_DialResponse {
dr := new(pb.Message_DialResponse)
dr.Status = status.Enum()
dr.StatusText = &text
return dr
}
Loading