Unverified Commit c6b40f96 authored by vyzo's avatar vyzo Committed by GitHub

Merge pull request #20 from libp2p/feat/parallel-dialback

parallelize dialbacks
parents 36aba7ce 2584eaf3
Pipeline #464 failed with stages
in 0 seconds
......@@ -32,7 +32,7 @@ var (
AutoNATBootDelay = 15 * time.Second
AutoNATRetryInterval = 90 * time.Second
AutoNATRefreshInterval = 15 * time.Minute
AutoNATRequestTimeout = 60 * time.Second
AutoNATRequestTimeout = 30 * time.Second
)
// AutoNAT is the interface for ambient NAT autodiscovery
......@@ -135,50 +135,84 @@ func (as *AmbientAutoNAT) autodetect() {
}
cli := NewAutoNATClient(as.host, as.getAddrs)
failures := 0
for _, pi := range peers {
ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout)
as.host.Peerstore().AddAddrs(pi.ID, pi.Addrs, pstore.TempAddrTTL)
a, err := cli.DialBack(ctx, pi.ID)
cancel()
switch {
case err == nil:
log.Debugf("NAT status is public; address through %s: %s", pi.ID.Pretty(), a.String())
as.mx.Lock()
as.addr = a
as.status = NATStatusPublic
as.confidence = 0
as.mx.Unlock()
return
ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout)
defer cancel()
var result struct {
sync.Mutex
private int
public int
pubaddr ma.Multiaddr
}
case IsDialError(err):
log.Debugf("dial error through %s: %s", pi.ID.Pretty(), err.Error())
failures++
if failures >= 3 || as.confidence >= 3 { // 3 times is enemy action
log.Debugf("NAT status is private")
as.mx.Lock()
as.status = NATStatusPrivate
as.confidence = 3
as.mx.Unlock()
return
}
probe := 3 - as.confidence
if probe == 0 {
probe = 1
}
if probe > len(peers) {
probe = len(peers)
}
default:
log.Debugf("Error dialing through %s: %s", pi.ID.Pretty(), err.Error())
}
var wg sync.WaitGroup
for _, pi := range peers[:probe] {
wg.Add(1)
go func(pi pstore.PeerInfo) {
defer wg.Done()
as.host.Peerstore().AddAddrs(pi.ID, pi.Addrs, pstore.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)
}
wg.Wait()
as.mx.Lock()
if failures > 0 {
as.status = NATStatusPrivate
as.confidence++
if result.public > 0 {
log.Debugf("NAT status is public")
if as.status == NATStatusPrivate {
// we are flipping our NATStatus, so confidence drops to 0
as.confidence = 0
} else if as.confidence < 3 {
as.confidence++
}
as.status = NATStatusPublic
as.addr = result.pubaddr
} else if result.private > 0 {
log.Debugf("NAT status is private")
if as.status == NATStatusPublic {
// we are flipping our NATStatus, so confidence drops to 0
as.confidence = 0
} else if as.confidence < 3 {
as.confidence++
}
as.status = NATStatusPrivate
as.addr = nil
} else if as.confidence > 0 {
// don't just flip to unknown, reduce confidence first
as.confidence--
} else {
as.status = NATStatusUnknown
as.confidence = 0
log.Debugf("NAT status is unknown")
as.status = NATStatusUnknown
as.addr = nil
}
as.mx.Unlock()
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment