From 1f8ed1d07b3e3a36c5aac9adb8d3fd77f8ea083d Mon Sep 17 00:00:00 2001 From: Will Scott Date: Thu, 13 Feb 2020 17:56:32 -0800 Subject: [PATCH] Cleanup structure of autonat. * incoming connections post a channel event - fix #40 * inbound connections reduce the frequency of probes - address #35 waiting on https://github.com/libp2p/go-libp2p/pull/747 for detecting local address changes --- autonat.go | 266 +++++++++++++++++++++++++----------------------- autonat_test.go | 6 +- client.go | 16 +-- go.mod | 2 + go.sum | 35 +++++++ notify.go | 23 +---- 6 files changed, 183 insertions(+), 165 deletions(-) diff --git a/autonat.go b/autonat.go index 2d6c978..bbc3383 100644 --- a/autonat.go +++ b/autonat.go @@ -4,28 +4,29 @@ import ( "context" "errors" "math/rand" - "sync" + "sync/atomic" "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" - "github.com/libp2p/go-libp2p-core/peerstore" + peerstore "github.com/libp2p/go-libp2p-peerstore" ma "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr-net" ) // NATStatus is the state of NAT as detected by the ambient service. type NATStatus int const ( - // NAT status is unknown; this means that the ambient service has not been + // NATStatusUnknown means that the ambient service has not been // able to decide the presence of NAT in the most recent attempt to test // dial through known autonat peers. initial state. NATStatusUnknown NATStatus = iota - // NAT status is publicly dialable + // NATStatusPublic means this node believes it is externally dialable NATStatusPublic - // NAT status is private network + // NATStatusPrivate means this node believes it is behind a NAT NATStatusPrivate ) @@ -50,46 +51,45 @@ type AmbientAutoNAT struct { ctx context.Context host host.Host - getAddrs GetAddrs - - mx sync.Mutex - peers map[peer.ID][]ma.Multiaddr - status NATStatus - addr ma.Multiaddr + candidatePeers chan network.Conn + observations chan autoNATResult + status atomic.Value // Reflects the confidence on of the NATStatus being private, as a single // dialback may fail for reasons unrelated to NAT. // If it is <3, then multiple autoNAT peers may be contacted for dialback // If only a single autoNAT peer is known, then the confidence increases // for each failure until it reaches 3. - confidence int + confidence int + lastInbound time.Time + lastProbe time.Time emitUnknown event.Emitter emitPublic event.Emitter emitPrivate event.Emitter } -// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host -// 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 - } +type autoNATResult struct { + NATStatus + address ma.Multiaddr +} +// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host +func NewAutoNAT(ctx context.Context, h host.Host) AutoNAT { 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, + ctx: ctx, + host: h, + candidatePeers: make(chan network.Conn, 5), + observations: make(chan autoNATResult, 1), emitUnknown: emitUnknown, emitPublic: emitPublic, emitPrivate: emitPrivate, } + as.status.Store(autoNATResult{NATStatusUnknown, nil}) h.Network().Notify(as) go as.background() @@ -97,15 +97,15 @@ func NewAutoNAT(ctx context.Context, h host.Host, getAddrs GetAddrs) AutoNAT { return as } +// Status returns the AutoNAT observed reachability status. func (as *AmbientAutoNAT) Status() NATStatus { - as.mx.Lock() - defer as.mx.Unlock() - return as.status + s := as.status.Load().(autoNATResult) + return s.NATStatus } -func (as *AmbientAutoNAT) updateStatus(s NATStatus) { - as.status = s - switch s { +func (as *AmbientAutoNAT) emitStatus() { + status := as.status.Load().(autoNATResult) + switch status.NATStatus { case NATStatusUnknown: as.emitUnknown.Emit(event.EvtLocalRoutabilityUnknown{}) case NATStatusPublic: @@ -115,158 +115,164 @@ func (as *AmbientAutoNAT) updateStatus(s NATStatus) { } } +// PublicAddr returns the publicly connectable Multiaddr of this node if one is known. func (as *AmbientAutoNAT) PublicAddr() (ma.Multiaddr, error) { - as.mx.Lock() - defer as.mx.Unlock() - - if as.status != NATStatusPublic { + s := as.status.Load().(autoNATResult) + if s.NATStatus != NATStatusPublic { return nil, errors.New("NAT Status is not public") } - return as.addr, nil + return s.address, nil } func (as *AmbientAutoNAT) background() { // wait a bit for the node to come online and establish some connections // before starting autodetection - select { - case <-time.After(AutoNATBootDelay): - case <-as.ctx.Done(): - return - } - + delay := AutoNATBootDelay for { - as.autodetect() - - delay := AutoNATRefreshInterval - if as.status == NATStatusUnknown { - delay = AutoNATRetryInterval - } - select { + // new connection occured. + case conn := <-as.candidatePeers: + if conn.Stat().Direction == network.DirInbound && manet.IsPublicAddr(conn.RemoteMultiaddr()) { + as.lastInbound = time.Now() + } + // TODO: network changed. + + // probe finished. + case result := <-as.observations: + as.recordObservation(result) case <-time.After(delay): case <-as.ctx.Done(): return } - } -} - -func (as *AmbientAutoNAT) autodetect() { - peers := as.getPeers() - if len(peers) == 0 { - log.Debugf("skipping NAT auto detection; no autonat peers") - return - } - - cli := NewAutoNATClient(as.host, as.getAddrs) - ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout) - defer cancel() - - var result struct { - sync.Mutex - private int - public int - pubaddr ma.Multiaddr + delay = as.scheduleProbe() } +} - probe := 3 - as.confidence - if probe == 0 { - probe = 1 - } - if probe > len(peers) { - probe = len(peers) +// scheduleProbe calculates when the next probe should be scheduled for, +// and launches it if that time is now. +func (as *AmbientAutoNAT) scheduleProbe() time.Duration { + // Our baseline is a probe every 'AutoNATRefreshInterval' + // This is modulated by: + // * recent inbound connections make us willing to wait up to 2x longer between probes. + // * low confidence makes us speed up between probes. + fixedNow := time.Now() + currentStatus := as.status.Load().(autoNATResult) + + nextProbe := fixedNow + if !as.lastProbe.IsZero() { + untilNext := AutoNATRefreshInterval + if currentStatus.NATStatus == NATStatusUnknown { + untilNext = AutoNATRetryInterval + } else if currentStatus.NATStatus == NATStatusPublic && as.lastInbound.After(as.lastProbe) { + untilNext *= 2 + } else if as.confidence < 3 { + untilNext = AutoNATRetryInterval + } + nextProbe = as.lastProbe.Add(untilNext) } - - var wg sync.WaitGroup - - for _, pi := range peers[:probe] { - wg.Add(1) - go func(pi peer.AddrInfo) { - defer wg.Done() - - as.host.Peerstore().AddAddrs(pi.ID, pi.Addrs, peerstore.TempAddrTTL) - a, err := cli.DialBack(ctx, pi.ID) - - switch { - case err == nil: - log.Debugf("Dialback through %s successful; public address is %s", pi.ID.Pretty(), a.String()) - result.Lock() - result.public++ - result.pubaddr = a - result.Unlock() - - case IsDialError(err): - log.Debugf("Dialback through %s failed", pi.ID.Pretty()) - result.Lock() - result.private++ - result.Unlock() - - default: - log.Debugf("Dialback error through %s: %s", pi.ID.Pretty(), err) - } - }(pi) + if fixedNow.After(nextProbe) || fixedNow == nextProbe { + as.lastProbe = fixedNow + go as.probeNextPeer() + return AutoNATRetryInterval } + return nextProbe.Sub(fixedNow) +} - wg.Wait() - - as.mx.Lock() - if result.public > 0 { +// Update the current status based on an observed result. +func (as *AmbientAutoNAT) recordObservation(observation autoNATResult) { + currentStatus := as.status.Load().(autoNATResult) + if observation.NATStatus == NATStatusPublic { log.Debugf("NAT status is public") - if as.status == NATStatusPrivate { + if currentStatus.NATStatus == NATStatusPrivate { // we are flipping our NATStatus, so confidence drops to 0 as.confidence = 0 } else if as.confidence < 3 { as.confidence++ } - as.addr = result.pubaddr - as.updateStatus(NATStatusPublic) - } else if result.private > 0 { + if observation.address != nil { + if currentStatus.address != nil && !observation.address.Equal(currentStatus.address) { + as.confidence-- + } + as.status.Store(observation) + } + if currentStatus.address != nil || observation.address != nil { + as.emitStatus() + } + } else if observation.NATStatus == NATStatusPrivate { log.Debugf("NAT status is private") - if as.status == NATStatusPublic { - // we are flipping our NATStatus, so confidence drops to 0 - as.confidence = 0 + if currentStatus.NATStatus == NATStatusPublic { + if as.confidence < 1 { + as.confidence-- + } else { + // we are flipping our NATStatus, so confidence drops to 0 + as.confidence = 0 + as.status.Store(observation) + as.emitStatus() + } } else if as.confidence < 3 { as.confidence++ + as.status.Store(observation) + as.emitStatus() } - 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.addr = nil - as.updateStatus(NATStatusUnknown) + as.status.Store(autoNATResult{NATStatusUnknown, nil}) + as.emitStatus() } - as.mx.Unlock() } -func (as *AmbientAutoNAT) getPeers() []peer.AddrInfo { - as.mx.Lock() - defer as.mx.Unlock() +func (as *AmbientAutoNAT) probe(pi *peer.AddrInfo) { + cli := NewAutoNATClient(as.host) + ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout) + defer cancel() - if len(as.peers) == 0 { - return nil + as.host.Peerstore().AddAddrs(pi.ID, pi.Addrs, peerstore.TempAddrTTL) + a, err := cli.DialBack(ctx, pi.ID) + + switch { + case err == nil: + log.Debugf("Dialback through %s successful; public address is %s", pi.ID.Pretty(), a.String()) + as.observations <- autoNATResult{NATStatusPublic, a} + case IsDialError(err): + log.Debugf("Dialback through %s failed", pi.ID.Pretty()) + as.observations <- autoNATResult{NATStatusPrivate, nil} + default: + as.observations <- autoNATResult{NATStatusUnknown, nil} } +} - var connected, others []peer.AddrInfo +func (as *AmbientAutoNAT) probeNextPeer() { + peers := as.host.Network().Peers() + if len(peers) == 0 { + return + } - for p, addrs := range as.peers { + connected := make([]peer.AddrInfo, 0, len(peers)) + others := make([]peer.AddrInfo, 0, len(peers)) + + for _, p := range peers { + info := as.host.Peerstore().PeerInfo(p) if as.host.Network().Connectedness(p) == network.Connected { - connected = append(connected, peer.AddrInfo{ID: p, Addrs: addrs}) + connected = append(connected, info) } else { - others = append(others, peer.AddrInfo{ID: p, Addrs: addrs}) + others = append(others, info) } } + // TODO: track and exclude recently probed peers. shufflePeers(connected) - if len(connected) < 3 { + if len(connected) > 0 { + as.probe(&connected[0]) + return + } else if len(others) > 0 { shufflePeers(others) - return append(connected, others...) - } else { - return connected + as.probe(&others[0]) } } diff --git a/autonat_test.go b/autonat_test.go index 74a429c..a7fa1f5 100644 --- a/autonat_test.go +++ b/autonat_test.go @@ -73,10 +73,8 @@ func newDialResponseError(status pb.Message_ResponseStatus, text string) *pb.Mes 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).mx.Lock() - a.(*AmbientAutoNAT).peers[ash.ID()] = ash.Addrs() - a.(*AmbientAutoNAT).mx.Unlock() + h.Peerstore().AddAddrs(ash.ID(), ash.Addrs(), time.Minute) + a := NewAutoNAT(ctx, h) return h, a } diff --git a/client.go b/client.go index 0d8549b..2bbc27b 100644 --- a/client.go +++ b/client.go @@ -27,21 +27,13 @@ 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 -// 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} +func NewAutoNATClient(h host.Host) AutoNATClient { + return &client{h: h} } type client struct { - h host.Host - getAddrs GetAddrs + h host.Host } func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error) { @@ -56,7 +48,7 @@ func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error) r := ggio.NewDelimitedReader(s, network.MessageSizeMax) w := ggio.NewDelimitedWriter(s) - req := newDialMessage(peer.AddrInfo{ID: c.h.ID(), Addrs: c.getAddrs()}) + req := newDialMessage(peer.AddrInfo{ID: c.h.ID(), Addrs: c.h.Addrs()}) err = w.WriteMsg(req) if err != nil { s.Reset() diff --git a/go.mod b/go.mod index 78df331..5535c4d 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,10 @@ require ( github.com/ipfs/go-log v0.0.1 github.com/libp2p/go-libp2p-blankhost v0.1.4 github.com/libp2p/go-libp2p-core v0.3.1-0.20191230184106-204a57d1afe1 + github.com/libp2p/go-libp2p-peerstore v0.1.4 github.com/libp2p/go-libp2p-swarm v0.2.2 github.com/multiformats/go-multiaddr v0.2.0 + github.com/multiformats/go-multiaddr-net v0.1.2 ) go 1.12 diff --git a/go.sum b/go.sum index 0e377a8..e16ef7e 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -29,6 +30,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= @@ -36,6 +38,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -57,17 +60,27 @@ github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJ github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= +github.com/ipfs/go-ds-badger v0.2.0/go.mod h1:471n2X/Qtk8rRO1iuxcgdwmHJdWjDj9VRGhaP/tvoZw= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= +github.com/ipfs/go-ds-leveldb v0.4.0/go.mod h1:NX127692WYenEjmlzyZunFv+f8nrKbH1s9eIaRNnhzs= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= @@ -112,6 +125,7 @@ github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGc github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= github.com/libp2p/go-libp2p-core v0.3.1-0.20191230184106-204a57d1afe1 h1:3WfZnKXp/5B9EIwbV9ts0W681Q+K1/ZQdlPH2dBXAHg= github.com/libp2p/go-libp2p-core v0.3.1-0.20191230184106-204a57d1afe1/go.mod h1:LRlbRHNBEfe8yypXy9+tfroNCfmGmYGjFGe5mU7bmWY= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= @@ -121,6 +135,8 @@ github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5gZJobNXCE/k= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= @@ -145,6 +161,7 @@ github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6 github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg= github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= @@ -205,6 +222,9 @@ github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.2 h1:P7zcBH9FRETdPkDrylcXVjQLQ2t1JQtNItZULWNWgeg= +github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= @@ -215,22 +235,31 @@ github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRH github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM= github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -269,6 +298,7 @@ github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go. github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -279,9 +309,12 @@ golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -328,6 +361,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -348,4 +382,5 @@ gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/notify.go b/notify.go index 4ea6561..258080f 100644 --- a/notify.go +++ b/notify.go @@ -18,25 +18,10 @@ func (as *AmbientAutoNAT) OpenedStream(net network.Network, s network.Stream) {} func (as *AmbientAutoNAT) ClosedStream(net network.Network, s network.Stream) {} func (as *AmbientAutoNAT) Connected(net network.Network, c network.Conn) { - p := c.RemotePeer() - - go func() { - // add some delay for identify - time.Sleep(AutoNATIdentifyDelay) - - protos, err := as.host.Peerstore().SupportsProtocols(p, AutoNATProto) - if err != nil { - log.Debugf("error retrieving supported protocols for peer %s: %s", p, err) - return - } - - if len(protos) > 0 { - log.Infof("Discovered AutoNAT peer %s", p.Pretty()) - as.mx.Lock() - as.peers[p] = as.host.Peerstore().Addrs(p) - as.mx.Unlock() - } - }() + select { + case as.candidatePeers <- c: + default: + } } func (as *AmbientAutoNAT) Disconnected(net network.Network, c network.Conn) {}