Skip to content

Commit

Permalink
Merge pull request #37 from libp2p/stabilize
Browse files Browse the repository at this point in the history
Emit events when NAT status changes
  • Loading branch information
vyzo authored Feb 6, 2020
2 parents 53f3cc4 + 0713eb4 commit 51b740b
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 5 deletions.
31 changes: 28 additions & 3 deletions p2p/host/autonat/autonat.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"
"time"

"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
Expand Down Expand Up @@ -61,6 +62,10 @@ type AmbientAutoNAT struct {
// If only a single autoNAT peer is known, then the confidence increases
// for each failure until it reaches 3.
confidence int

emitUnknown event.Emitter
emitPublic event.Emitter
emitPrivate event.Emitter
}

// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host
Expand All @@ -70,12 +75,20 @@ func NewAutoNAT(ctx context.Context, h host.Host, getAddrs GetAddrs) AutoNAT {
getAddrs = h.Addrs
}

emitUnknown, _ := h.EventBus().Emitter(new(event.EvtLocalRoutabilityUnknown))
emitPublic, _ := h.EventBus().Emitter(new(event.EvtLocalRoutabilityPublic))
emitPrivate, _ := h.EventBus().Emitter(new(event.EvtLocalRoutabilityPrivate))

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

emitUnknown: emitUnknown,
emitPublic: emitPublic,
emitPrivate: emitPrivate,
}

h.Network().Notify(as)
Expand All @@ -90,6 +103,18 @@ func (as *AmbientAutoNAT) Status() NATStatus {
return as.status
}

func (as *AmbientAutoNAT) updateStatus(s NATStatus) {
as.status = s
switch s {
case NATStatusUnknown:
as.emitUnknown.Emit(event.EvtLocalRoutabilityUnknown{})
case NATStatusPublic:
as.emitPublic.Emit(event.EvtLocalRoutabilityPublic{})
case NATStatusPrivate:
as.emitPrivate.Emit(event.EvtLocalRoutabilityPrivate{})
}
}

func (as *AmbientAutoNAT) PublicAddr() (ma.Multiaddr, error) {
as.mx.Lock()
defer as.mx.Unlock()
Expand Down Expand Up @@ -194,8 +219,8 @@ func (as *AmbientAutoNAT) autodetect() {
} else if as.confidence < 3 {
as.confidence++
}
as.status = NATStatusPublic
as.addr = result.pubaddr
as.updateStatus(NATStatusPublic)
} else if result.private > 0 {
log.Debugf("NAT status is private")
if as.status == NATStatusPublic {
Expand All @@ -204,15 +229,15 @@ func (as *AmbientAutoNAT) autodetect() {
} else if as.confidence < 3 {
as.confidence++
}
as.status = NATStatusPrivate
as.addr = nil
as.updateStatus(NATStatusPrivate)
} else if as.confidence > 0 {
// don't just flip to unknown, reduce confidence first
as.confidence--
} else {
log.Debugf("NAT status is unknown")
as.status = NATStatusUnknown
as.addr = nil
as.updateStatus(NATStatusUnknown)
}
as.mx.Unlock()
}
Expand Down
38 changes: 36 additions & 2 deletions p2p/host/autonat/autonat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"time"

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

"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"

ggio "github.com/gogo/protobuf/io"
bhost "github.com/libp2p/go-libp2p-blankhost"
Expand Down Expand Up @@ -96,6 +96,12 @@ func TestAutoNATPrivate(t *testing.T) {
hs := makeAutoNATServicePrivate(ctx, t)
hc, an := makeAutoNAT(ctx, t, hs)

// subscribe to AutoNat events
s, err := hc.EventBus().Subscribe(&event.EvtLocalRoutabilityPrivate{})
if err != nil {
t.Fatalf("failed to subscribe to event EvtLocalRoutabilityPrivate, err=%s", err)
}

status := an.Status()
if status != NATStatusUnknown {
t.Fatalf("unexpected NAT status: %d", status)
Expand All @@ -108,6 +114,17 @@ func TestAutoNATPrivate(t *testing.T) {
if status != NATStatusPrivate {
t.Fatalf("unexpected NAT status: %d", status)
}

select {
case e := <-s.Out():
_, ok := e.(event.EvtLocalRoutabilityPrivate)
if !ok {
t.Fatal("got wrong event type from the bus")
}

case <-time.After(1 * time.Second):
t.Fatal("failed to get the EvtLocalRoutabilityPrivate event from the bus")
}
}

func TestAutoNATPublic(t *testing.T) {
Expand All @@ -117,6 +134,12 @@ func TestAutoNATPublic(t *testing.T) {
hs := makeAutoNATServicePublic(ctx, t)
hc, an := makeAutoNAT(ctx, t, hs)

// subscribe to AutoNat events
s, err := hc.EventBus().Subscribe(&event.EvtLocalRoutabilityPublic{})
if err != nil {
t.Fatalf("failed to subscribe to event EvtLocalRoutabilityPublic, err=%s", err)
}

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

select {
case e := <-s.Out():
_, ok := e.(event.EvtLocalRoutabilityPublic)
if !ok {
t.Fatal("got wrong event type from the bus")
}

case <-time.After(1 * time.Second):
t.Fatal("failed to get the EvtLocalRoutabilityPublic event from the bus")
}
}

0 comments on commit 51b740b

Please sign in to comment.