github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/simulation/events.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:43</date> 10 //</624450114257162240> 11 12 13 package simulation 14 15 import ( 16 "context" 17 "sync" 18 19 "github.com/ethereum/go-ethereum/p2p/enode" 20 "github.com/ethereum/go-ethereum/p2p/simulations" 21 ) 22 23 //PeerEvent是Simulation.PeerEvents返回的通道类型。 24 type PeerEvent struct { 25 //node id是捕获事件的节点的ID。 26 NodeID enode.ID 27 //PeerID是捕获事件的对等节点的ID。 28 PeerID enode.ID 29 //事件是捕获的事件。 30 Event *simulations.Event 31 //错误是事件监视期间可能发生的错误。 32 Error error 33 } 34 35 //PeerEventsFilter定义一个对PeerEvents的筛选器,以排除具有 36 //定义的属性。使用PeerEventsFilter方法设置所需选项。 37 type PeerEventsFilter struct { 38 eventType simulations.EventType 39 40 connUp *bool 41 42 msgReceive *bool 43 protocol *string 44 msgCode *uint64 45 } 46 47 //NewPeerEventsFilter返回新的PeerEventsFilter实例。 48 func NewPeerEventsFilter() *PeerEventsFilter { 49 return &PeerEventsFilter{} 50 } 51 52 //连接将筛选器设置为两个节点连接时的事件。 53 func (f *PeerEventsFilter) Connect() *PeerEventsFilter { 54 f.eventType = simulations.EventTypeConn 55 b := true 56 f.connUp = &b 57 return f 58 } 59 60 //DROP将筛选器设置为两个节点断开连接时的事件。 61 func (f *PeerEventsFilter) Drop() *PeerEventsFilter { 62 f.eventType = simulations.EventTypeConn 63 b := false 64 f.connUp = &b 65 return f 66 } 67 68 //ReceivedMessages将筛选器设置为仅接收的消息。 69 func (f *PeerEventsFilter) ReceivedMessages() *PeerEventsFilter { 70 f.eventType = simulations.EventTypeMsg 71 b := true 72 f.msgReceive = &b 73 return f 74 } 75 76 //sent messages将筛选器设置为只发送消息。 77 func (f *PeerEventsFilter) SentMessages() *PeerEventsFilter { 78 f.eventType = simulations.EventTypeMsg 79 b := false 80 f.msgReceive = &b 81 return f 82 } 83 84 //协议将筛选器设置为仅一个消息协议。 85 func (f *PeerEventsFilter) Protocol(p string) *PeerEventsFilter { 86 f.eventType = simulations.EventTypeMsg 87 f.protocol = &p 88 return f 89 } 90 91 //msg code将筛选器设置为仅一个msg代码。 92 func (f *PeerEventsFilter) MsgCode(c uint64) *PeerEventsFilter { 93 f.eventType = simulations.EventTypeMsg 94 f.msgCode = &c 95 return f 96 } 97 98 //PeerEvents返回由管理PeerEvents捕获的事件通道 99 //具有提供的nodeid的订阅节点。可以将其他筛选器设置为忽略 100 //不相关的事件。 101 func (s *Simulation) PeerEvents(ctx context.Context, ids []enode.ID, filters ...*PeerEventsFilter) <-chan PeerEvent { 102 eventC := make(chan PeerEvent) 103 104 //等待组以确保已建立对管理对等事件的所有订阅 105 //在此函数返回之前。 106 var subsWG sync.WaitGroup 107 for _, id := range ids { 108 s.shutdownWG.Add(1) 109 subsWG.Add(1) 110 go func(id enode.ID) { 111 defer s.shutdownWG.Done() 112 113 events := make(chan *simulations.Event) 114 sub := s.Net.Events().Subscribe(events) 115 defer sub.Unsubscribe() 116 117 subsWG.Done() 118 119 for { 120 select { 121 case <-ctx.Done(): 122 if err := ctx.Err(); err != nil { 123 select { 124 case eventC <- PeerEvent{NodeID: id, Error: err}: 125 case <-s.Done(): 126 } 127 } 128 return 129 case <-s.Done(): 130 return 131 case e := <-events: 132 //忽略控制事件 133 if e.Control { 134 continue 135 } 136 match := len(filters) == 0 //如果没有匹配所有事件的筛选器 137 for _, f := range filters { 138 if f.eventType == simulations.EventTypeConn && e.Conn != nil { 139 if *f.connUp != e.Conn.Up { 140 continue 141 } 142 //所有连接过滤器参数匹配,中断循环 143 match = true 144 break 145 } 146 if f.eventType == simulations.EventTypeMsg && e.Msg != nil { 147 if f.msgReceive != nil && *f.msgReceive != e.Msg.Received { 148 continue 149 } 150 if f.protocol != nil && *f.protocol != e.Msg.Protocol { 151 continue 152 } 153 if f.msgCode != nil && *f.msgCode != e.Msg.Code { 154 continue 155 } 156 //所有消息过滤器参数匹配,中断循环 157 match = true 158 break 159 } 160 } 161 var peerID enode.ID 162 switch e.Type { 163 case simulations.EventTypeConn: 164 peerID = e.Conn.One 165 if peerID == id { 166 peerID = e.Conn.Other 167 } 168 case simulations.EventTypeMsg: 169 peerID = e.Msg.One 170 if peerID == id { 171 peerID = e.Msg.Other 172 } 173 } 174 if match { 175 select { 176 case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Event: e}: 177 case <-ctx.Done(): 178 if err := ctx.Err(); err != nil { 179 select { 180 case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Error: err}: 181 case <-s.Done(): 182 } 183 } 184 return 185 case <-s.Done(): 186 return 187 } 188 } 189 case err := <-sub.Err(): 190 if err != nil { 191 select { 192 case eventC <- PeerEvent{NodeID: id, Error: err}: 193 case <-ctx.Done(): 194 if err := ctx.Err(); err != nil { 195 select { 196 case eventC <- PeerEvent{NodeID: id, Error: err}: 197 case <-s.Done(): 198 } 199 } 200 return 201 case <-s.Done(): 202 return 203 } 204 } 205 } 206 } 207 }(id) 208 } 209 210 //等待所有订阅 211 subsWG.Wait() 212 return eventC 213 } 214