Skip to content

Commit be32b5b

Browse files
authored
Identify: emit useful events after identification (#2759)
* Identify should emit useful events after identification * Compare strings rather than objects * Include other fields in emitted event * Sort addrs when comparing in test
1 parent 5d1c4a6 commit be32b5b

File tree

3 files changed

+92
-21
lines changed

3 files changed

+92
-21
lines changed

core/event/identify.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,40 @@
11
package event
22

3-
import "github.com/libp2p/go-libp2p/core/peer"
3+
import (
4+
"github.com/libp2p/go-libp2p/core/network"
5+
"github.com/libp2p/go-libp2p/core/peer"
6+
"github.com/libp2p/go-libp2p/core/protocol"
7+
"github.com/libp2p/go-libp2p/core/record"
8+
"github.com/multiformats/go-multiaddr"
9+
)
410

511
// EvtPeerIdentificationCompleted is emitted when the initial identification round for a peer is completed.
612
type EvtPeerIdentificationCompleted struct {
713
// Peer is the ID of the peer whose identification succeeded.
814
Peer peer.ID
15+
16+
// Conn is the connection we identified.
17+
Conn network.Conn
18+
19+
// ListenAddrs is the list of addresses the peer is listening on.
20+
ListenAddrs []multiaddr.Multiaddr
21+
22+
// Protocols is the list of protocols the peer advertised on this connection.
23+
Protocols []protocol.ID
24+
25+
// SignedPeerRecord is the provided signed peer record of the peer. May be nil.
26+
SignedPeerRecord *record.Envelope
27+
28+
// AgentVersion is like a UserAgent string in browsers, or client version in
29+
// bittorrent includes the client name and client.
30+
AgentVersion string
31+
32+
// ProtocolVersion is the protocolVersion field in the identify message
33+
ProtocolVersion string
34+
35+
// ObservedAddr is the our side's connection address as observed by the
36+
// peer. This is not verified, the peer could return anything here.
37+
ObservedAddr multiaddr.Multiaddr
938
}
1039

1140
// EvtPeerIdentificationFailed is emitted when the initial identification round for a peer failed.

p2p/protocol/identify/id.go

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,6 @@ func (ids *idService) IdentifyWait(c network.Conn) <-chan struct{} {
400400
ids.emitters.evtPeerIdentificationFailed.Emit(event.EvtPeerIdentificationFailed{Peer: c.RemotePeer(), Reason: err})
401401
return
402402
}
403-
404-
ids.emitters.evtPeerIdentificationCompleted.Emit(event.EvtPeerIdentificationCompleted{Peer: c.RemotePeer()})
405403
}()
406404

407405
return e.IdentifyWaitChan
@@ -711,8 +709,16 @@ func (ids *idService) consumeMessage(mes *pb.Identify, c network.Conn, isPush bo
711709
})
712710
}
713711

714-
// mes.ObservedAddr
715-
ids.consumeObservedAddress(mes.GetObservedAddr(), c)
712+
obsAddr, err := ma.NewMultiaddrBytes(mes.GetObservedAddr())
713+
if err != nil {
714+
log.Debugf("error parsing received observed addr for %s: %s", c, err)
715+
obsAddr = nil
716+
}
717+
718+
if obsAddr != nil {
719+
// TODO refactor this to use the emitted events instead of having this func call explicitly.
720+
ids.observedAddrs.Record(c, obsAddr)
721+
}
716722

717723
// mes.ListenAddrs
718724
laddrs := mes.GetListenAddrs()
@@ -763,6 +769,7 @@ func (ids *idService) consumeMessage(mes *pb.Identify, c network.Conn, isPush bo
763769
signedAddrs, err := ids.consumeSignedPeerRecord(c.RemotePeer(), signedPeerRecord)
764770
if err != nil {
765771
log.Debugf("failed to consume signed peer record: %s", err)
772+
signedPeerRecord = nil
766773
} else {
767774
addrs = signedAddrs
768775
}
@@ -786,6 +793,18 @@ func (ids *idService) consumeMessage(mes *pb.Identify, c network.Conn, isPush bo
786793

787794
// get the key from the other side. we may not have it (no-auth transport)
788795
ids.consumeReceivedPubKey(c, mes.PublicKey)
796+
797+
ids.emitters.evtPeerIdentificationCompleted.Emit(event.EvtPeerIdentificationCompleted{
798+
Peer: c.RemotePeer(),
799+
Conn: c,
800+
ListenAddrs: lmaddrs,
801+
Protocols: mesProtocols,
802+
SignedPeerRecord: signedPeerRecord,
803+
ObservedAddr: obsAddr,
804+
ProtocolVersion: pv,
805+
AgentVersion: av,
806+
})
807+
789808
}
790809

791810
func (ids *idService) consumeSignedPeerRecord(p peer.ID, signedPeerRecord *record.Envelope) ([]ma.Multiaddr, error) {
@@ -919,20 +938,6 @@ func HasConsistentTransport(a ma.Multiaddr, green []ma.Multiaddr) bool {
919938
return false
920939
}
921940

922-
func (ids *idService) consumeObservedAddress(observed []byte, c network.Conn) {
923-
if observed == nil {
924-
return
925-
}
926-
927-
maddr, err := ma.NewMultiaddrBytes(observed)
928-
if err != nil {
929-
log.Debugf("error parsing received observed addr for %s: %s", c, err)
930-
return
931-
}
932-
933-
ids.observedAddrs.Record(c, maddr)
934-
}
935-
936941
// addConnWithLock assuems caller holds the connsMu lock
937942
func (ids *idService) addConnWithLock(c network.Conn) {
938943
_, found := ids.conns[c]

p2p/protocol/identify/id_test.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"slices"
78
"sync"
89
"testing"
910
"time"
@@ -200,12 +201,47 @@ func TestIDService(t *testing.T) {
200201

201202
// test that we received the "identify completed" event.
202203
select {
203-
case <-sub.Out():
204+
case evtAny := <-sub.Out():
205+
assertCorrectEvtPeerIdentificationCompleted(t, evtAny, h2)
204206
case <-time.After(3 * time.Second):
205207
t.Fatalf("expected EvtPeerIdentificationCompleted event within 10 seconds; none received")
206208
}
207209
}
208210

211+
func assertCorrectEvtPeerIdentificationCompleted(t *testing.T, evtAny interface{}, other host.Host) {
212+
t.Helper()
213+
evt := evtAny.(event.EvtPeerIdentificationCompleted)
214+
require.NotNil(t, evt.Conn)
215+
require.Equal(t, other.ID(), evt.Peer)
216+
217+
require.Equal(t, len(other.Addrs()), len(evt.ListenAddrs))
218+
if len(other.Addrs()) == len(evt.ListenAddrs) {
219+
otherAddrsStrings := make([]string, len(other.Addrs()))
220+
evtAddrStrings := make([]string, len(evt.ListenAddrs))
221+
for i, a := range other.Addrs() {
222+
otherAddrsStrings[i] = a.String()
223+
evtAddrStrings[i] = evt.ListenAddrs[i].String()
224+
}
225+
slices.Sort(otherAddrsStrings)
226+
slices.Sort(evtAddrStrings)
227+
require.Equal(t, otherAddrsStrings, evtAddrStrings)
228+
}
229+
230+
otherProtos := other.Mux().Protocols()
231+
slices.Sort(otherProtos)
232+
evtProtos := evt.Protocols
233+
slices.Sort(evtProtos)
234+
require.Equal(t, otherProtos, evtProtos)
235+
idFromSignedRecord, err := peer.IDFromPublicKey(evt.SignedPeerRecord.PublicKey)
236+
require.NoError(t, err)
237+
require.Equal(t, other.ID(), idFromSignedRecord)
238+
require.Equal(t, peer.PeerRecordEnvelopePayloadType, evt.SignedPeerRecord.PayloadType)
239+
var peerRecord peer.PeerRecord
240+
evt.SignedPeerRecord.TypedRecord(&peerRecord)
241+
require.Equal(t, other.ID(), peerRecord.PeerID)
242+
require.Equal(t, other.Addrs(), peerRecord.Addrs)
243+
}
244+
209245
func TestProtoMatching(t *testing.T) {
210246
tcp1, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/1234")
211247
tcp2, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/2345")
@@ -665,7 +701,8 @@ func TestLargeIdentifyMessage(t *testing.T) {
665701

666702
// test that we received the "identify completed" event.
667703
select {
668-
case <-sub.Out():
704+
case evtAny := <-sub.Out():
705+
assertCorrectEvtPeerIdentificationCompleted(t, evtAny, h2)
669706
case <-time.After(3 * time.Second):
670707
t.Fatalf("expected EvtPeerIdentificationCompleted event within 3 seconds; none received")
671708
}

0 commit comments

Comments
 (0)