diff --git a/net/conn/dial.go b/net/conn/dial.go index 8bab13d86..af5d9228f 100644 --- a/net/conn/dial.go +++ b/net/conn/dial.go @@ -6,6 +6,7 @@ import ( 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" manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" peer "github.com/jbenet/go-ipfs/peer" @@ -14,22 +15,44 @@ import ( // Dial connects to a particular peer, over a given network // Example: d.Dial(ctx, "udp", peer) func (d *Dialer) Dial(ctx context.Context, network string, remote peer.Peer) (Conn, error) { - laddr := d.LocalPeer.NetAddress(network) - if laddr == nil { - return nil, fmt.Errorf("No local address for network %s", network) - } - raddr := remote.NetAddress(network) if raddr == nil { return nil, fmt.Errorf("No remote address for network %s", network) } + return d.DialAddr(ctx, raddr, remote) +} + +// DialAddr connects to a peer over a particular address +// Ensures raddr is part of peer.Addresses() +// Example: d.DialAddr(ctx, peer.Addresses()[0], peer) +func (d *Dialer) DialAddr(ctx context.Context, raddr ma.Multiaddr, remote peer.Peer) (Conn, error) { + + found := false + for _, addr := range remote.Addresses() { + if addr.Equal(raddr) { + found = true + } + } + if !found { + return nil, fmt.Errorf("address %s is not in peer %s", raddr, remote) + } + + network, _, err := manet.DialArgs(raddr) + if err != nil { + return nil, err + } + + laddr := d.LocalPeer.NetAddress(network) + if laddr == nil { + return nil, fmt.Errorf("No local address for network %s", network) + } if strings.HasPrefix(raddr.String(), "/ip4/0.0.0.0") { return nil, fmt.Errorf("Attempted to connect to zero address: %s", raddr) } remote.SetType(peer.Remote) - remote, err := d.Peerstore.Add(remote) + remote, err = d.Peerstore.Add(remote) if err != nil { log.Errorf("Error putting peer into peerstore: %s", remote) } diff --git a/net/conn/dial_test.go b/net/conn/dial_test.go index 50ef51e77..f3d3808d0 100644 --- a/net/conn/dial_test.go +++ b/net/conn/dial_test.go @@ -157,3 +157,73 @@ func TestDialer(t *testing.T) { l.Close() cancel() } + +func TestDialAddr(t *testing.T) { + // t.Skip("Skipping in favor of another test") + + p1, err := setupPeer("/ip4/127.0.0.1/tcp/4334") + if err != nil { + t.Fatal("error setting up peer", err) + } + + p2, err := setupPeer("/ip4/127.0.0.1/tcp/4335") + if err != nil { + t.Fatal("error setting up peer", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + laddr := p1.NetAddress("tcp") + if laddr == nil { + t.Fatal("Listen address is nil.") + } + + ps1 := peer.NewPeerstore() + ps2 := peer.NewPeerstore() + ps1.Add(p1) + ps2.Add(p2) + + l, err := Listen(ctx, laddr, p1, ps1) + if err != nil { + t.Fatal(err) + } + + go echoListen(ctx, l) + + d := &Dialer{ + Peerstore: ps2, + LocalPeer: p2, + } + + raddr := p1.NetAddress("tcp") + if raddr == nil { + t.Fatal("Dial address is nil.") + } + + c, err := d.DialAddr(ctx, raddr, p1) + if err != nil { + t.Fatal("error dialing peer", err) + } + + // fmt.Println("sending") + c.Out() <- []byte("beep") + c.Out() <- []byte("boop") + + out := <-c.In() + // fmt.Println("recving", string(out)) + data := string(out) + if data != "beep" { + t.Error("unexpected conn output", data) + } + + out = <-c.In() + data = string(out) + if string(out) != "boop" { + t.Error("unexpected conn output", data) + } + + // fmt.Println("closing") + c.Close() + l.Close() + cancel() +}