Commit 207156fa authored by Juan Batiz-Benet's avatar Juan Batiz-Benet
Browse files

p2p/net/swarm: async grabbing of best conn

this is actually pretty important in case some peers end
up changing addrs, so others dont fail dialing simply for
picking the wrong addr to start with.
parent 9d9e2a3b
...@@ -294,42 +294,83 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) { ...@@ -294,42 +294,83 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remoteAddrs []ma.Multiaddr) (conn.Conn, error) { func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remoteAddrs []ma.Multiaddr) (conn.Conn, error) {
// try to connect to one of the peer's known addresses. // try to connect to one of the peer's known addresses.
// for simplicity, we do this sequentially. // we dial concurrently to each of the addresses, which:
// A future commit will do this asynchronously. // * makes the process faster overall
// * attempts to get the fastest connection available.
// * mitigates the waste of trying bad addresses
log.Debugf("%s swarm dialing %s %s", s.local, p, remoteAddrs) log.Debugf("%s swarm dialing %s %s", s.local, p, remoteAddrs)
var err error
ctx, cancel := context.WithCancel(ctx)
defer cancel() // cancel work when we exit func
foundConn := make(chan struct{})
conns := make(chan conn.Conn, len(remoteAddrs))
errs := make(chan error, len(remoteAddrs))
//TODO: rate limiting just in case?
for _, addr := range remoteAddrs { for _, addr := range remoteAddrs {
log.Debugf("%s swarm dialing %s %s", s.local, p, addr) go func(addr ma.Multiaddr) {
var connC conn.Conn connC, err := s.dialAddr(ctx, d, p, addr)
connC, err = d.Dial(ctx, addr, p)
if err != nil {
log.Info("%s --> %s dial attempt failed: %s", s.local, p, err)
continue
}
// if the connection is not to whom we thought it would be... // check parent still wants our results
if connC.RemotePeer() != p { select {
log.Infof("misdial to %s through %s (got %s)", p, addr, connC.RemotePeer()) case <-foundConn:
connC.Close() if connC != nil {
continue connC.Close()
} }
return
default:
}
// if the connection is to ourselves... if err != nil {
// this can happen TONS when Loopback addrs are advertized. errs <- err
// (this should be caught by two checks above, but let's just make sure.) } else if connC == nil {
if connC.RemotePeer() == s.local { errs <- fmt.Errorf("failed to dial %s %s", p, addr)
log.Infof("misdial to %s through %s", p, addr) } else {
connC.Close() conns <- connC
continue }
} }(addr)
}
// success! we got one! err := fmt.Errorf("failed to dial %s", p)
return connC, nil for i := 0; i < len(remoteAddrs); i++ {
select {
case err = <-errs:
log.Info(err)
case connC := <-conns:
// take the first + return asap
close(foundConn)
return connC, nil
}
} }
return nil, err
}
func (s *Swarm) dialAddr(ctx context.Context, d *conn.Dialer, p peer.ID, addr ma.Multiaddr) (conn.Conn, error) {
log.Debugf("%s swarm dialing %s %s", s.local, p, addr)
connC, err := d.Dial(ctx, addr, p)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("%s --> %s dial attempt failed: %s", s.local, p, err)
} }
return nil, fmt.Errorf("failed to dial %s", p)
// if the connection is not to whom we thought it would be...
remotep := connC.RemotePeer()
if remotep != p {
connC.Close()
return nil, fmt.Errorf("misdial to %s through %s (got %s)", p, addr, remotep)
}
// if the connection is to ourselves...
// this can happen TONS when Loopback addrs are advertized.
// (this should be caught by two checks above, but let's just make sure.)
if remotep == s.local {
connC.Close()
return nil, fmt.Errorf("misdial to %s through %s (got self)", p, addr)
}
// success! we got one!
return connC, nil
} }
// dialConnSetup is the setup logic for a connection from the dial side. it // dialConnSetup is the setup logic for a connection from the dial side. it
......
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