|
|
@@ -20,16 +20,18 @@ import (
|
|
|
"context"
|
|
|
"sync"
|
|
|
|
|
|
- "github.com/ethereum/go-ethereum/p2p"
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
+ "github.com/ethereum/go-ethereum/p2p/simulations"
|
|
|
)
|
|
|
|
|
|
// PeerEvent is the type of the channel returned by Simulation.PeerEvents.
|
|
|
type PeerEvent struct {
|
|
|
// NodeID is the ID of node that the event is caught on.
|
|
|
NodeID enode.ID
|
|
|
+ // PeerID is the ID of the peer node that the event is caught on.
|
|
|
+ PeerID enode.ID
|
|
|
// Event is the event that is caught.
|
|
|
- Event *p2p.PeerEvent
|
|
|
+ Event *simulations.Event
|
|
|
// Error is the error that may have happened during event watching.
|
|
|
Error error
|
|
|
}
|
|
|
@@ -37,9 +39,13 @@ type PeerEvent struct {
|
|
|
// PeerEventsFilter defines a filter on PeerEvents to exclude messages with
|
|
|
// defined properties. Use PeerEventsFilter methods to set required options.
|
|
|
type PeerEventsFilter struct {
|
|
|
- t *p2p.PeerEventType
|
|
|
- protocol *string
|
|
|
- msgCode *uint64
|
|
|
+ eventType simulations.EventType
|
|
|
+
|
|
|
+ connUp *bool
|
|
|
+
|
|
|
+ msgReceive *bool
|
|
|
+ protocol *string
|
|
|
+ msgCode *uint64
|
|
|
}
|
|
|
|
|
|
// NewPeerEventsFilter returns a new PeerEventsFilter instance.
|
|
|
@@ -47,20 +53,48 @@ func NewPeerEventsFilter() *PeerEventsFilter {
|
|
|
return &PeerEventsFilter{}
|
|
|
}
|
|
|
|
|
|
-// Type sets the filter to only one peer event type.
|
|
|
-func (f *PeerEventsFilter) Type(t p2p.PeerEventType) *PeerEventsFilter {
|
|
|
- f.t = &t
|
|
|
+// Connect sets the filter to events when two nodes connect.
|
|
|
+func (f *PeerEventsFilter) Connect() *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeConn
|
|
|
+ b := true
|
|
|
+ f.connUp = &b
|
|
|
+ return f
|
|
|
+}
|
|
|
+
|
|
|
+// Drop sets the filter to events when two nodes disconnect.
|
|
|
+func (f *PeerEventsFilter) Drop() *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeConn
|
|
|
+ b := false
|
|
|
+ f.connUp = &b
|
|
|
+ return f
|
|
|
+}
|
|
|
+
|
|
|
+// ReceivedMessages sets the filter to only messages that are received.
|
|
|
+func (f *PeerEventsFilter) ReceivedMessages() *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeMsg
|
|
|
+ b := true
|
|
|
+ f.msgReceive = &b
|
|
|
+ return f
|
|
|
+}
|
|
|
+
|
|
|
+// SentMessages sets the filter to only messages that are sent.
|
|
|
+func (f *PeerEventsFilter) SentMessages() *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeMsg
|
|
|
+ b := false
|
|
|
+ f.msgReceive = &b
|
|
|
return f
|
|
|
}
|
|
|
|
|
|
// Protocol sets the filter to only one message protocol.
|
|
|
func (f *PeerEventsFilter) Protocol(p string) *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeMsg
|
|
|
f.protocol = &p
|
|
|
return f
|
|
|
}
|
|
|
|
|
|
// MsgCode sets the filter to only one msg code.
|
|
|
func (f *PeerEventsFilter) MsgCode(c uint64) *PeerEventsFilter {
|
|
|
+ f.eventType = simulations.EventTypeMsg
|
|
|
f.msgCode = &c
|
|
|
return f
|
|
|
}
|
|
|
@@ -80,19 +114,8 @@ func (s *Simulation) PeerEvents(ctx context.Context, ids []enode.ID, filters ...
|
|
|
go func(id enode.ID) {
|
|
|
defer s.shutdownWG.Done()
|
|
|
|
|
|
- client, err := s.Net.GetNode(id).Client()
|
|
|
- if err != nil {
|
|
|
- subsWG.Done()
|
|
|
- eventC <- PeerEvent{NodeID: id, Error: err}
|
|
|
- return
|
|
|
- }
|
|
|
- events := make(chan *p2p.PeerEvent)
|
|
|
- sub, err := client.Subscribe(ctx, "admin", events, "peerEvents")
|
|
|
- if err != nil {
|
|
|
- subsWG.Done()
|
|
|
- eventC <- PeerEvent{NodeID: id, Error: err}
|
|
|
- return
|
|
|
- }
|
|
|
+ events := make(chan *simulations.Event)
|
|
|
+ sub := s.Net.Events().Subscribe(events)
|
|
|
defer sub.Unsubscribe()
|
|
|
|
|
|
subsWG.Done()
|
|
|
@@ -110,28 +133,55 @@ func (s *Simulation) PeerEvents(ctx context.Context, ids []enode.ID, filters ...
|
|
|
case <-s.Done():
|
|
|
return
|
|
|
case e := <-events:
|
|
|
+ // ignore control events
|
|
|
+ if e.Control {
|
|
|
+ continue
|
|
|
+ }
|
|
|
match := len(filters) == 0 // if there are no filters match all events
|
|
|
for _, f := range filters {
|
|
|
- if f.t != nil && *f.t != e.Type {
|
|
|
- continue
|
|
|
+ if f.eventType == simulations.EventTypeConn && e.Conn != nil {
|
|
|
+ if *f.connUp != e.Conn.Up {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // all connection filter parameters matched, break the loop
|
|
|
+ match = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if f.eventType == simulations.EventTypeMsg && e.Msg != nil {
|
|
|
+ if f.msgReceive != nil && *f.msgReceive != e.Msg.Received {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if f.protocol != nil && *f.protocol != e.Msg.Protocol {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if f.msgCode != nil && *f.msgCode != e.Msg.Code {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // all message filter parameters matched, break the loop
|
|
|
+ match = true
|
|
|
+ break
|
|
|
}
|
|
|
- if f.protocol != nil && *f.protocol != e.Protocol {
|
|
|
- continue
|
|
|
+ }
|
|
|
+ var peerID enode.ID
|
|
|
+ switch e.Type {
|
|
|
+ case simulations.EventTypeConn:
|
|
|
+ peerID = e.Conn.One
|
|
|
+ if peerID == id {
|
|
|
+ peerID = e.Conn.Other
|
|
|
}
|
|
|
- if f.msgCode != nil && e.MsgCode != nil && *f.msgCode != *e.MsgCode {
|
|
|
- continue
|
|
|
+ case simulations.EventTypeMsg:
|
|
|
+ peerID = e.Msg.One
|
|
|
+ if peerID == id {
|
|
|
+ peerID = e.Msg.Other
|
|
|
}
|
|
|
- // all filter parameters matched, break the loop
|
|
|
- match = true
|
|
|
- break
|
|
|
}
|
|
|
if match {
|
|
|
select {
|
|
|
- case eventC <- PeerEvent{NodeID: id, Event: e}:
|
|
|
+ case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Event: e}:
|
|
|
case <-ctx.Done():
|
|
|
if err := ctx.Err(); err != nil {
|
|
|
select {
|
|
|
- case eventC <- PeerEvent{NodeID: id, Error: err}:
|
|
|
+ case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Error: err}:
|
|
|
case <-s.Done():
|
|
|
}
|
|
|
}
|