github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:47</date> 10 //</624342673469214720> 11 12 //版权所有2018 Go Ethereum作者 13 //此文件是Go以太坊库的一部分。 14 // 15 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 16 //根据GNU发布的较低通用公共许可证的条款 17 //自由软件基金会,或者许可证的第3版,或者 18 //(由您选择)任何更高版本。 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package simulation 29 30 import ( 31 "context" 32 "sync" 33 34 "github.com/ethereum/go-ethereum/p2p/discover" 35 36 "github.com/ethereum/go-ethereum/p2p" 37 ) 38 39 // 40 type PeerEvent struct { 41 // 42 NodeID discover.NodeID 43 // 44 Event *p2p.PeerEvent 45 // 46 Error error 47 } 48 49 // 50 // 51 type PeerEventsFilter struct { 52 t *p2p.PeerEventType 53 protocol *string 54 msgCode *uint64 55 } 56 57 // 58 func NewPeerEventsFilter() *PeerEventsFilter { 59 return &PeerEventsFilter{} 60 } 61 62 // 63 func (f *PeerEventsFilter) Type(t p2p.PeerEventType) *PeerEventsFilter { 64 f.t = &t 65 return f 66 } 67 68 // 69 func (f *PeerEventsFilter) Protocol(p string) *PeerEventsFilter { 70 f.protocol = &p 71 return f 72 } 73 74 // 75 func (f *PeerEventsFilter) MsgCode(c uint64) *PeerEventsFilter { 76 f.msgCode = &c 77 return f 78 } 79 80 // 81 // 82 // 83 func (s *Simulation) PeerEvents(ctx context.Context, ids []discover.NodeID, filters ...*PeerEventsFilter) <-chan PeerEvent { 84 eventC := make(chan PeerEvent) 85 86 // 87 // 88 var subsWG sync.WaitGroup 89 for _, id := range ids { 90 s.shutdownWG.Add(1) 91 subsWG.Add(1) 92 go func(id discover.NodeID) { 93 defer s.shutdownWG.Done() 94 95 client, err := s.Net.GetNode(id).Client() 96 if err != nil { 97 subsWG.Done() 98 eventC <- PeerEvent{NodeID: id, Error: err} 99 return 100 } 101 events := make(chan *p2p.PeerEvent) 102 sub, err := client.Subscribe(ctx, "admin", events, "peerEvents") 103 if err != nil { 104 subsWG.Done() 105 eventC <- PeerEvent{NodeID: id, Error: err} 106 return 107 } 108 defer sub.Unsubscribe() 109 110 subsWG.Done() 111 112 for { 113 select { 114 case <-ctx.Done(): 115 if err := ctx.Err(); err != nil { 116 select { 117 case eventC <- PeerEvent{NodeID: id, Error: err}: 118 case <-s.Done(): 119 } 120 } 121 return 122 case <-s.Done(): 123 return 124 case e := <-events: 125 match := len(filters) == 0 // 126 for _, f := range filters { 127 if f.t != nil && *f.t != e.Type { 128 continue 129 } 130 if f.protocol != nil && *f.protocol != e.Protocol { 131 continue 132 } 133 if f.msgCode != nil && e.MsgCode != nil && *f.msgCode != *e.MsgCode { 134 continue 135 } 136 // 137 match = true 138 break 139 } 140 if match { 141 select { 142 case eventC <- PeerEvent{NodeID: id, Event: e}: 143 case <-ctx.Done(): 144 if err := ctx.Err(); err != nil { 145 select { 146 case eventC <- PeerEvent{NodeID: id, Error: err}: 147 case <-s.Done(): 148 } 149 } 150 return 151 case <-s.Done(): 152 return 153 } 154 } 155 case err := <-sub.Err(): 156 if err != nil { 157 select { 158 case eventC <- PeerEvent{NodeID: id, Error: err}: 159 case <-ctx.Done(): 160 if err := ctx.Err(); err != nil { 161 select { 162 case eventC <- PeerEvent{NodeID: id, Error: err}: 163 case <-s.Done(): 164 } 165 } 166 return 167 case <-s.Done(): 168 return 169 } 170 } 171 } 172 } 173 }(id) 174 } 175 176 // 177 subsWG.Wait() 178 return eventC 179 } 180