github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/discovery.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 //</624342672139620352> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package network 29 30 import ( 31 "context" 32 "fmt" 33 "sync" 34 35 "github.com/ethereum/go-ethereum/swarm/pot" 36 ) 37 38 // 39 40 // 41 type discPeer struct { 42 *BzzPeer 43 overlay Overlay 44 sentPeers bool // 45 mtx sync.RWMutex 46 peers map[string]bool // 47 depth uint8 // 48 } 49 50 // 51 func newDiscovery(p *BzzPeer, o Overlay) *discPeer { 52 d := &discPeer{ 53 overlay: o, 54 BzzPeer: p, 55 peers: make(map[string]bool), 56 } 57 // 58 d.seen(d) 59 return d 60 } 61 62 // 63 func (d *discPeer) HandleMsg(ctx context.Context, msg interface{}) error { 64 switch msg := msg.(type) { 65 66 case *peersMsg: 67 return d.handlePeersMsg(msg) 68 69 case *subPeersMsg: 70 return d.handleSubPeersMsg(msg) 71 72 default: 73 return fmt.Errorf("unknown message type: %T", msg) 74 } 75 } 76 77 // 78 func NotifyDepth(depth uint8, h Overlay) { 79 f := func(val OverlayConn, po int, _ bool) bool { 80 dp, ok := val.(*discPeer) 81 if ok { 82 dp.NotifyDepth(depth) 83 } 84 return true 85 } 86 h.EachConn(nil, 255, f) 87 } 88 89 // 90 func NotifyPeer(p OverlayAddr, k Overlay) { 91 f := func(val OverlayConn, po int, _ bool) bool { 92 dp, ok := val.(*discPeer) 93 if ok { 94 dp.NotifyPeer(p, uint8(po)) 95 } 96 return true 97 } 98 k.EachConn(p.Address(), 255, f) 99 } 100 101 // 102 // 103 // 104 // 105 func (d *discPeer) NotifyPeer(a OverlayAddr, po uint8) { 106 // 107 if (po < d.getDepth() && pot.ProxCmp(d.localAddr, d, a) != 1) || d.seen(a) { 108 return 109 } 110 // 111 resp := &peersMsg{ 112 Peers: []*BzzAddr{ToAddr(a)}, 113 } 114 go d.Send(context.TODO(), resp) 115 } 116 117 // 118 // 119 func (d *discPeer) NotifyDepth(po uint8) { 120 // 121 go d.Send(context.TODO(), &subPeersMsg{Depth: po}) 122 } 123 124 /* 125 126 127 128 129 130 131 132 133 134 135 136 137 138 */ 139 140 141 // 142 // 143 // 144 type peersMsg struct { 145 Peers []*BzzAddr 146 } 147 148 // 149 func (msg peersMsg) String() string { 150 return fmt.Sprintf("%T: %v", msg, msg.Peers) 151 } 152 153 // 154 // 155 // 156 func (d *discPeer) handlePeersMsg(msg *peersMsg) error { 157 // 158 if len(msg.Peers) == 0 { 159 return nil 160 } 161 162 for _, a := range msg.Peers { 163 d.seen(a) 164 NotifyPeer(a, d.overlay) 165 } 166 return d.overlay.Register(toOverlayAddrs(msg.Peers...)) 167 } 168 169 // 170 type subPeersMsg struct { 171 Depth uint8 172 } 173 174 // 175 func (msg subPeersMsg) String() string { 176 return fmt.Sprintf("%T: request peers > PO%02d. ", msg, msg.Depth) 177 } 178 179 func (d *discPeer) handleSubPeersMsg(msg *subPeersMsg) error { 180 if !d.sentPeers { 181 d.setDepth(msg.Depth) 182 var peers []*BzzAddr 183 d.overlay.EachConn(d.Over(), 255, func(p OverlayConn, po int, isproxbin bool) bool { 184 if pob, _ := pof(d, d.localAddr, 0); pob > po { 185 return false 186 } 187 if !d.seen(p) { 188 peers = append(peers, ToAddr(p.Off())) 189 } 190 return true 191 }) 192 if len(peers) > 0 { 193 // 194 go d.Send(context.TODO(), &peersMsg{Peers: peers}) 195 } 196 } 197 d.sentPeers = true 198 return nil 199 } 200 201 // 202 // 203 func (d *discPeer) seen(p OverlayPeer) bool { 204 d.mtx.Lock() 205 defer d.mtx.Unlock() 206 k := string(p.Address()) 207 if d.peers[k] { 208 return true 209 } 210 d.peers[k] = true 211 return false 212 } 213 214 func (d *discPeer) getDepth() uint8 { 215 d.mtx.RLock() 216 defer d.mtx.RUnlock() 217 return d.depth 218 } 219 func (d *discPeer) setDepth(depth uint8) { 220 d.mtx.Lock() 221 defer d.mtx.Unlock() 222 d.depth = depth 223 } 224