github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/hive.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 //</624342672273838080> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package network 29 30 import ( 31 "fmt" 32 "sync" 33 "time" 34 35 "github.com/ethereum/go-ethereum/common/hexutil" 36 "github.com/ethereum/go-ethereum/p2p" 37 "github.com/ethereum/go-ethereum/p2p/discover" 38 "github.com/ethereum/go-ethereum/swarm/log" 39 "github.com/ethereum/go-ethereum/swarm/state" 40 ) 41 42 /* 43 44 45 46 47 48 */ 49 50 51 // 52 type Overlay interface { 53 // 54 SuggestPeer() (OverlayAddr, int, bool) 55 // 56 On(OverlayConn) (depth uint8, changed bool) 57 Off(OverlayConn) 58 // 59 Register([]OverlayAddr) error 60 // 61 EachConn([]byte, int, func(OverlayConn, int, bool) bool) 62 // 63 EachAddr([]byte, int, func(OverlayAddr, int, bool) bool) 64 // 65 String() string 66 // 67 BaseAddr() []byte 68 // 69 Healthy(*PeerPot) *Health 70 } 71 72 // 73 type HiveParams struct { 74 Discovery bool // 75 PeersBroadcastSetSize uint8 // 76 MaxPeersPerRequest uint8 // 77 KeepAliveInterval time.Duration 78 } 79 80 // 81 func NewHiveParams() *HiveParams { 82 return &HiveParams{ 83 Discovery: true, 84 PeersBroadcastSetSize: 3, 85 MaxPeersPerRequest: 5, 86 KeepAliveInterval: 500 * time.Millisecond, 87 } 88 } 89 90 // 91 type Hive struct { 92 *HiveParams // 93 Overlay // 94 Store state.Store // 95 addPeer func(*discover.Node) // 96 // 97 lock sync.Mutex 98 ticker *time.Ticker 99 } 100 101 // 102 // 103 // 104 // 105 func NewHive(params *HiveParams, overlay Overlay, store state.Store) *Hive { 106 return &Hive{ 107 HiveParams: params, 108 Overlay: overlay, 109 Store: store, 110 } 111 } 112 113 // 114 // 115 // 116 func (h *Hive) Start(server *p2p.Server) error { 117 log.Info("Starting hive", "baseaddr", fmt.Sprintf("%x", h.BaseAddr()[:4])) 118 // 119 if h.Store != nil { 120 log.Info("Detected an existing store. trying to load peers") 121 if err := h.loadPeers(); err != nil { 122 log.Error(fmt.Sprintf("%08x hive encoutered an error trying to load peers", h.BaseAddr()[:4])) 123 return err 124 } 125 } 126 // 127 h.addPeer = server.AddPeer 128 // 129 h.ticker = time.NewTicker(h.KeepAliveInterval) 130 // 131 go h.connect() 132 return nil 133 } 134 135 // 136 func (h *Hive) Stop() error { 137 log.Info(fmt.Sprintf("%08x hive stopping, saving peers", h.BaseAddr()[:4])) 138 h.ticker.Stop() 139 if h.Store != nil { 140 if err := h.savePeers(); err != nil { 141 return fmt.Errorf("could not save peers to persistence store: %v", err) 142 } 143 if err := h.Store.Close(); err != nil { 144 return fmt.Errorf("could not close file handle to persistence store: %v", err) 145 } 146 } 147 log.Info(fmt.Sprintf("%08x hive stopped, dropping peers", h.BaseAddr()[:4])) 148 h.EachConn(nil, 255, func(p OverlayConn, _ int, _ bool) bool { 149 log.Info(fmt.Sprintf("%08x dropping peer %08x", h.BaseAddr()[:4], p.Address()[:4])) 150 p.Drop(nil) 151 return true 152 }) 153 154 log.Info(fmt.Sprintf("%08x all peers dropped", h.BaseAddr()[:4])) 155 return nil 156 } 157 158 // 159 // 160 // 161 func (h *Hive) connect() { 162 for range h.ticker.C { 163 164 addr, depth, changed := h.SuggestPeer() 165 if h.Discovery && changed { 166 NotifyDepth(uint8(depth), h) 167 } 168 if addr == nil { 169 continue 170 } 171 172 log.Trace(fmt.Sprintf("%08x hive connect() suggested %08x", h.BaseAddr()[:4], addr.Address()[:4])) 173 under, err := discover.ParseNode(string(addr.(Addr).Under())) 174 if err != nil { 175 log.Warn(fmt.Sprintf("%08x unable to connect to bee %08x: invalid node URL: %v", h.BaseAddr()[:4], addr.Address()[:4], err)) 176 continue 177 } 178 log.Trace(fmt.Sprintf("%08x attempt to connect to bee %08x", h.BaseAddr()[:4], addr.Address()[:4])) 179 h.addPeer(under) 180 } 181 } 182 183 // 184 func (h *Hive) Run(p *BzzPeer) error { 185 dp := newDiscovery(p, h) 186 depth, changed := h.On(dp) 187 // 188 if h.Discovery { 189 if changed { 190 // 191 NotifyDepth(depth, h) 192 } else { 193 // 194 dp.NotifyDepth(depth) 195 } 196 } 197 NotifyPeer(p.Off(), h) 198 defer h.Off(dp) 199 return dp.Run(dp.HandleMsg) 200 } 201 202 // 203 // 204 func (h *Hive) NodeInfo() interface{} { 205 return h.String() 206 } 207 208 // 209 // 210 func (h *Hive) PeerInfo(id discover.NodeID) interface{} { 211 addr := NewAddrFromNodeID(id) 212 return struct { 213 OAddr hexutil.Bytes 214 UAddr hexutil.Bytes 215 }{ 216 OAddr: addr.OAddr, 217 UAddr: addr.UAddr, 218 } 219 } 220 221 // 222 func ToAddr(pa OverlayPeer) *BzzAddr { 223 if addr, ok := pa.(*BzzAddr); ok { 224 return addr 225 } 226 if p, ok := pa.(*discPeer); ok { 227 return p.BzzAddr 228 } 229 return pa.(*BzzPeer).BzzAddr 230 } 231 232 // 233 func (h *Hive) loadPeers() error { 234 var as []*BzzAddr 235 err := h.Store.Get("peers", &as) 236 if err != nil { 237 if err == state.ErrNotFound { 238 log.Info(fmt.Sprintf("hive %08x: no persisted peers found", h.BaseAddr()[:4])) 239 return nil 240 } 241 return err 242 } 243 log.Info(fmt.Sprintf("hive %08x: peers loaded", h.BaseAddr()[:4])) 244 245 return h.Register(toOverlayAddrs(as...)) 246 } 247 248 // 249 func toOverlayAddrs(as ...*BzzAddr) (oas []OverlayAddr) { 250 for _, a := range as { 251 oas = append(oas, OverlayAddr(a)) 252 } 253 return 254 } 255 256 // 257 func (h *Hive) savePeers() error { 258 var peers []*BzzAddr 259 h.Overlay.EachAddr(nil, 256, func(pa OverlayAddr, i int, _ bool) bool { 260 if pa == nil { 261 log.Warn(fmt.Sprintf("empty addr: %v", i)) 262 return true 263 } 264 apa := ToAddr(pa) 265 log.Trace("saving peer", "peer", apa) 266 peers = append(peers, apa) 267 return true 268 }) 269 if err := h.Store.Put("peers", peers); err != nil { 270 return fmt.Errorf("could not save peers: %v", err) 271 } 272 return nil 273 } 274