diff --git a/p2p/net/conn/conn.go b/p2p/net/conn/conn.go index 396cabb16935ff892985a2d82e883802f23f1759..5335f6e8d872730221c4e2da0a054702dd5c3de8 100644 --- a/p2p/net/conn/conn.go +++ b/p2p/net/conn/conn.go @@ -128,6 +128,10 @@ func (c *singleConn) Write(buf []byte) (int, error) { return c.maconn.Write(buf) } +func (c *singleConn) SetRemotePeer(id peer.ID) { + c.remote = id +} + // ID returns the ID of a given Conn. func ID(c Conn) string { l := fmt.Sprintf("%s/%s", c.LocalMultiaddr(), c.LocalPeer().Pretty()) diff --git a/p2p/net/conn/interface.go b/p2p/net/conn/interface.go index 816284f35bef96357672b33f5603056747208d58..bc215aff1b431f8e6370315720cb6b7b7798ef84 100644 --- a/p2p/net/conn/interface.go +++ b/p2p/net/conn/interface.go @@ -24,6 +24,7 @@ type PeerConn interface { RemotePeer() peer.ID RemotePublicKey() ic.PubKey RemoteMultiaddr() ma.Multiaddr + SetRemotePeer(peer.ID) } // Conn is a generic message-based Peer-to-Peer connection. diff --git a/p2p/net/conn/secure_conn.go b/p2p/net/conn/secure_conn.go index 6aa16f92087d935e5a792fe45e4f017d6b77cdf4..5d88ca2707bda4d08d280a4baddc5b155a0a860b 100644 --- a/p2p/net/conn/secure_conn.go +++ b/p2p/net/conn/secure_conn.go @@ -122,3 +122,7 @@ func (c *secureConn) Write(buf []byte) (int, error) { func (c *secureConn) ReleaseMsg(m []byte) { c.secure.ReadWriter().ReleaseMsg(m) } + +func (c *secureConn) SetRemotePeer(id peer.ID) { + c.insecure.SetRemotePeer(id) +} diff --git a/p2p/net/mock/mock_conn.go b/p2p/net/mock/mock_conn.go index f0fe6c1cebb49262a4950c2ee12e90f80a8d5546..377760a29e4e6d59be0f2836f9fa7b592675504a 100644 --- a/p2p/net/mock/mock_conn.go +++ b/p2p/net/mock/mock_conn.go @@ -147,3 +147,7 @@ func (c *conn) RemotePeer() peer.ID { func (c *conn) RemotePublicKey() ic.PubKey { return c.remotePubKey } + +func (c *conn) SetRemotePeer(id peer.ID) { + c.remote = id +} diff --git a/p2p/net/swarm/swarm_conn.go b/p2p/net/swarm/swarm_conn.go index 96700ba835fbfe66b6dfe2bdb85e3c320c2da07d..a2f748af86d65b2604f5a755cc48791140a54c99 100644 --- a/p2p/net/swarm/swarm_conn.go +++ b/p2p/net/swarm/swarm_conn.go @@ -91,6 +91,10 @@ func (c *Conn) Close() error { return c.StreamConn().Close() } +func (c *Conn) SetRemotePeer(id peer.ID) { + c.RawConn().SetRemotePeer(id) +} + func wrapConn(psc *ps.Conn) (*Conn, error) { // grab the underlying connection. if _, ok := psc.NetConn().(conn.Conn); !ok { diff --git a/p2p/protocol/identify/id.go b/p2p/protocol/identify/id.go index 83e5059ee25863b88497308e69918c628d285187..c4fc43362b7cbafd45700493269866dd2f859af3 100644 --- a/p2p/protocol/identify/id.go +++ b/p2p/protocol/identify/id.go @@ -1,11 +1,14 @@ package identify import ( + "fmt" "strings" "sync" semver "github.com/coreos/go-semver/semver" ggio "github.com/gogo/protobuf/io" + ci "github.com/ipfs/go-libp2p-crypto" + "github.com/ipfs/go-libp2p-peer" pstore "github.com/ipfs/go-libp2p-peerstore" host "github.com/ipfs/go-libp2p/p2p/host" mstream "github.com/ipfs/go-libp2p/p2p/metrics/stream" @@ -150,6 +153,16 @@ func (ids *IDService) populateMessage(mes *pb.Identify, c inet.Conn) { mes.Protocols[i] = string(p) } + if c.RemotePeer() == "" { + pubk := ids.Host.Peerstore().PubKey(ids.Host.ID()) + data, err := pubk.Bytes() + if err != nil { + log.Error("marshaling our public key: ", err) + } else { + mes.PublicKey = data + } + } + // observed address so other side is informed of their // "public" address, at least in relation to us. mes.ObservedAddr = c.RemoteMultiaddr().Bytes() @@ -169,9 +182,35 @@ func (ids *IDService) populateMessage(mes *pb.Identify, c inet.Conn) { mes.AgentVersion = &av } +func checkPubKeyID(mes *pb.Identify, c inet.Conn) error { + if len(mes.PublicKey) == 0 { + return fmt.Errorf("remote peer has no ID and no public key was sent") + } + + pubk, err := ci.UnmarshalPublicKey(mes.PublicKey) + if err != nil { + return err + } + + pid, err := peer.IDFromPublicKey(pubk) + if err != nil { + return err + } + + c.SetRemotePeer(pid) + return nil +} + func (ids *IDService) consumeMessage(mes *pb.Identify, c inet.Conn) { p := c.RemotePeer() + if p == "" { + err := checkPubKeyID(mes, c) + if err != nil { + log.Warning("no peerID set: ", err) + } + } + // mes.Protocols // mes.ObservedAddr