Commit 4d877044 authored by Juan Batiz-Benet's avatar Juan Batiz-Benet
Browse files

p2p/net/swarm: fix connect self problems

This adds two checks after a successful conn.Dial
* if the remote peer is not who we wanted, close conn
* if the remove peer is outselves, close conn

(the second is redundant, but the codebase may evolve to
end up disabling the first check, so keeping the second
in place helps)

note:
Loopback addresses are actually sent out (they _have to be_,
in cases where there are >1 node in the same machine), so
many times when trying connections, nodes end up dialing
themselves.
parent 63145110
......@@ -10,6 +10,7 @@ import (
lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)
// Dial connects to a peer.
......@@ -56,23 +57,11 @@ func (s *Swarm) Dial(ctx context.Context, p peer.ID) (*Conn, error) {
PrivateKey: sk,
}
// try to connect to one of the peer's known addresses.
// for simplicity, we do this sequentially.
// A future commit will do this asynchronously.
var connC conn.Conn
var err error
for _, addr := range remoteAddrs {
connC, err = d.Dial(ctx, addr, p)
if err == nil {
break
}
}
// try to get a connection to any addr
connC, err := s.dialAddrs(ctx, d, p, remoteAddrs)
if err != nil {
return nil, err
}
if connC == nil {
err = fmt.Errorf("failed to dial %s", p)
}
// ok try to setup the new connection.
swarmC, err := dialConnSetup(ctx, s, connC)
......@@ -87,6 +76,39 @@ func (s *Swarm) Dial(ctx context.Context, p peer.ID) (*Conn, error) {
return swarmC, nil
}
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.
// for simplicity, we do this sequentially.
// A future commit will do this asynchronously.
for _, addr := range remoteAddrs {
connC, err := d.Dial(ctx, addr, p)
if err != nil {
continue
}
// if the connection is not to whom we thought it would be...
if connC.RemotePeer() != p {
log.Infof("misdial to %s through %s (got %s)", p, addr, connC.RemoteMultiaddr())
connC.Close()
continue
}
// 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 connC.RemotePeer() == s.local {
log.Infof("misdial to %s through %s", p, addr)
connC.Close()
continue
}
// success! we got one!
return connC, nil
}
return nil, fmt.Errorf("failed to dial %s", p)
}
// dialConnSetup is the setup logic for a connection from the dial side. it
// needs to add the Conn to the StreamSwarm, then run newConnSetup
func dialConnSetup(ctx context.Context, s *Swarm, connC conn.Conn) (*Conn, error) {
......
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