github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/p2p/switch.go (about) 1 package p2p 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "net" 7 "sync" 8 "time" 9 10 log "github.com/sirupsen/logrus" 11 "github.com/tendermint/go-crypto" 12 cmn "github.com/tendermint/tmlibs/common" 13 14 cfg "github.com/bytom/bytom/config" 15 "github.com/bytom/bytom/consensus" 16 "github.com/bytom/bytom/crypto/ed25519" 17 "github.com/bytom/bytom/errors" 18 "github.com/bytom/bytom/event" 19 "github.com/bytom/bytom/p2p/connection" 20 "github.com/bytom/bytom/p2p/discover/dht" 21 "github.com/bytom/bytom/p2p/discover/mdns" 22 "github.com/bytom/bytom/p2p/netutil" 23 "github.com/bytom/bytom/p2p/security" 24 "github.com/bytom/bytom/version" 25 ) 26 27 const ( 28 logModule = "p2p" 29 30 minNumOutboundPeers = 4 31 maxNumLANPeers = 5 32 ) 33 34 //pre-define errors for connecting fail 35 var ( 36 ErrDuplicatePeer = errors.New("Duplicate peer") 37 ErrConnectSelf = errors.New("Connect self") 38 ErrConnectSpvPeer = errors.New("Outbound connect spv peer") 39 ) 40 41 type discv interface { 42 ReadRandomNodes(buf []*dht.Node) (n int) 43 } 44 45 type lanDiscv interface { 46 Subscribe() (*event.Subscription, error) 47 Stop() 48 } 49 50 type Security interface { 51 DoFilter(ip string, pubKey string) error 52 IsBanned(ip string, level byte, reason string) bool 53 RegisterFilter(filter security.Filter) 54 Start() error 55 } 56 57 // Switch handles peer connections and exposes an API to receive incoming messages 58 // on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one 59 // or more `Channels`. So while sending outgoing messages is typically performed on the peer, 60 // incoming messages are received on the reactor. 61 type Switch struct { 62 cmn.BaseService 63 64 Config *cfg.Config 65 peerConfig *PeerConfig 66 listeners []Listener 67 reactors map[string]Reactor 68 chDescs []*connection.ChannelDescriptor 69 reactorsByCh map[byte]Reactor 70 peers *PeerSet 71 dialing *cmn.CMap 72 nodeInfo *NodeInfo // our node info 73 nodePrivKey crypto.PrivKeyEd25519 // our node privkey 74 discv discv 75 lanDiscv lanDiscv 76 security Security 77 } 78 79 // NewSwitch create a new Switch and set discover. 80 func NewSwitch(config *cfg.Config) (*Switch, error) { 81 var err error 82 var l Listener 83 var listenAddr string 84 var discv *dht.Network 85 var lanDiscv *mdns.LANDiscover 86 87 config.P2P.PrivateKey, err = config.NodeKey() 88 if err != nil { 89 return nil, err 90 } 91 92 bytes, err := hex.DecodeString(config.P2P.PrivateKey) 93 if err != nil { 94 return nil, err 95 } 96 97 var newKey [64]byte 98 copy(newKey[:], bytes) 99 privKey := crypto.PrivKeyEd25519(newKey) 100 if !config.VaultMode { 101 // Create listener 102 l, listenAddr = GetListener(config.P2P) 103 discv, err = dht.NewDiscover(config, ed25519.PrivateKey(bytes), l.ExternalAddress().Port) 104 if err != nil { 105 return nil, err 106 } 107 if config.P2P.LANDiscover { 108 lanDiscv = mdns.NewLANDiscover(mdns.NewProtocol(config.ChainID), int(l.ExternalAddress().Port)) 109 } 110 } 111 112 return newSwitch(config, discv, lanDiscv, l, privKey, listenAddr) 113 } 114 115 // newSwitch creates a new Switch with the given config. 116 func newSwitch(config *cfg.Config, discv discv, lanDiscv lanDiscv, l Listener, priv crypto.PrivKeyEd25519, listenAddr string) (*Switch, error) { 117 sw := &Switch{ 118 Config: config, 119 peerConfig: DefaultPeerConfig(config.P2P), 120 reactors: make(map[string]Reactor), 121 chDescs: make([]*connection.ChannelDescriptor, 0), 122 reactorsByCh: make(map[byte]Reactor), 123 peers: NewPeerSet(), 124 dialing: cmn.NewCMap(), 125 nodePrivKey: priv, 126 discv: discv, 127 lanDiscv: lanDiscv, 128 nodeInfo: NewNodeInfo(config, priv.PubKey().Unwrap().(crypto.PubKeyEd25519), listenAddr), 129 security: security.NewSecurity(config), 130 } 131 132 sw.AddListener(l) 133 sw.BaseService = *cmn.NewBaseService(nil, "P2P Switch", sw) 134 return sw, nil 135 } 136 137 // OnStart implements BaseService. It starts all the reactors, peers, and listeners. 138 func (sw *Switch) OnStart() error { 139 for _, reactor := range sw.reactors { 140 if _, err := reactor.Start(); err != nil { 141 return err 142 } 143 } 144 145 sw.security.RegisterFilter(sw.nodeInfo) 146 sw.security.RegisterFilter(sw.peers) 147 if err := sw.security.Start(); err != nil { 148 return err 149 } 150 151 for _, listener := range sw.listeners { 152 go sw.listenerRoutine(listener) 153 } 154 go sw.ensureOutboundPeersRoutine() 155 go sw.connectLANPeersRoutine() 156 157 return nil 158 } 159 160 // OnStop implements BaseService. It stops all listeners, peers, and reactors. 161 func (sw *Switch) OnStop() { 162 if sw.Config.P2P.LANDiscover { 163 sw.lanDiscv.Stop() 164 } 165 166 for _, listener := range sw.listeners { 167 listener.Stop() 168 } 169 sw.listeners = nil 170 171 for _, peer := range sw.peers.List() { 172 peer.Stop() 173 sw.peers.Remove(peer) 174 } 175 176 for _, reactor := range sw.reactors { 177 reactor.Stop() 178 } 179 } 180 181 // AddPeer performs the P2P handshake with a peer 182 // that already has a SecretConnection. If all goes well, 183 // it starts the peer and adds it to the switch. 184 // NOTE: This performs a blocking handshake before the peer is added. 185 // CONTRACT: If error is returned, peer is nil, and conn is immediately closed. 186 func (sw *Switch) AddPeer(pc *peerConn, isLAN bool) error { 187 peerNodeInfo, err := pc.HandshakeTimeout(sw.nodeInfo, sw.peerConfig.HandshakeTimeout) 188 if err != nil { 189 return err 190 } 191 192 if err := version.Status.CheckUpdate(sw.nodeInfo.Version, peerNodeInfo.Version, peerNodeInfo.RemoteAddr); err != nil { 193 return err 194 } 195 if err := sw.nodeInfo.CompatibleWith(peerNodeInfo); err != nil { 196 return err 197 } 198 199 peer := newPeer(pc, peerNodeInfo, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, isLAN) 200 if err := sw.security.DoFilter(peer.RemoteAddrHost(), peer.PubKey().String()); err != nil { 201 return err 202 } 203 204 if pc.outbound && !peer.ServiceFlag().IsEnable(consensus.SFFullNode) { 205 return ErrConnectSpvPeer 206 } 207 208 // Start peer 209 if sw.IsRunning() { 210 if err := sw.startInitPeer(peer); err != nil { 211 return err 212 } 213 } 214 215 return sw.peers.Add(peer) 216 } 217 218 // AddReactor adds the given reactor to the switch. 219 // NOTE: Not goroutine safe. 220 func (sw *Switch) AddReactor(name string, reactor Reactor) Reactor { 221 // Validate the reactor. 222 // No two reactors can share the same channel. 223 for _, chDesc := range reactor.GetChannels() { 224 chID := chDesc.ID 225 if sw.reactorsByCh[chID] != nil { 226 cmn.PanicSanity(fmt.Sprintf("Channel %X has multiple reactors %v & %v", chID, sw.reactorsByCh[chID], reactor)) 227 } 228 sw.chDescs = append(sw.chDescs, chDesc) 229 sw.reactorsByCh[chID] = reactor 230 } 231 sw.reactors[name] = reactor 232 reactor.SetSwitch(sw) 233 return reactor 234 } 235 236 // AddListener adds the given listener to the switch for listening to incoming peer connections. 237 // NOTE: Not goroutine safe. 238 func (sw *Switch) AddListener(l Listener) { 239 sw.listeners = append(sw.listeners, l) 240 } 241 242 //DialPeerWithAddress dial node from net address 243 func (sw *Switch) DialPeerWithAddress(addr *NetAddress) error { 244 log.WithFields(log.Fields{"module": logModule, "address": addr}).Debug("Dialing peer") 245 sw.dialing.Set(addr.IP.String(), addr) 246 defer sw.dialing.Delete(addr.IP.String()) 247 if err := sw.security.DoFilter(addr.IP.String(), ""); err != nil { 248 return err 249 } 250 251 pc, err := newOutboundPeerConn(addr, sw.nodePrivKey, sw.peerConfig) 252 if err != nil { 253 log.WithFields(log.Fields{"module": logModule, "address": addr, " err": err}).Warn("DialPeer fail on newOutboundPeerConn") 254 return err 255 } 256 257 if err = sw.AddPeer(pc, addr.isLAN); err != nil { 258 log.WithFields(log.Fields{"module": logModule, "address": addr, " err": err}).Warn("DialPeer fail on switch AddPeer") 259 pc.CloseConn() 260 return err 261 } 262 log.WithFields(log.Fields{"module": logModule, "address": addr, "peer num": sw.peers.Size()}).Debug("DialPeer added peer") 263 return nil 264 } 265 266 func (sw *Switch) IsBanned(ip string, level byte, reason string) bool { 267 return sw.security.IsBanned(ip, level, reason) 268 } 269 270 //IsDialing prevent duplicate dialing 271 func (sw *Switch) IsDialing(addr *NetAddress) bool { 272 return sw.dialing.Has(addr.IP.String()) 273 } 274 275 // IsListening returns true if the switch has at least one listener. 276 // NOTE: Not goroutine safe. 277 func (sw *Switch) IsListening() bool { 278 return len(sw.listeners) > 0 279 } 280 281 // Listeners returns the list of listeners the switch listens on. 282 // NOTE: Not goroutine safe. 283 func (sw *Switch) Listeners() []Listener { 284 return sw.listeners 285 } 286 287 // NumPeers Returns the count of outbound/inbound and outbound-dialing peers. 288 func (sw *Switch) NumPeers() (lan, outbound, inbound, dialing int) { 289 peers := sw.peers.List() 290 for _, peer := range peers { 291 if peer.outbound && !peer.isLAN { 292 outbound++ 293 } else { 294 inbound++ 295 } 296 if peer.isLAN { 297 lan++ 298 } 299 } 300 dialing = sw.dialing.Size() 301 return 302 } 303 304 // NodeInfo returns the switch's NodeInfo. 305 // NOTE: Not goroutine safe. 306 func (sw *Switch) NodeInfo() *NodeInfo { 307 return sw.nodeInfo 308 } 309 310 //Peers return switch peerset 311 func (sw *Switch) Peers() *PeerSet { 312 return sw.peers 313 } 314 315 // StopPeerForError disconnects from a peer due to external error. 316 func (sw *Switch) StopPeerForError(peer *Peer, reason interface{}) { 317 log.WithFields(log.Fields{"module": logModule, "peer": peer, " err": reason}).Debug("stopping peer for error") 318 sw.stopAndRemovePeer(peer, reason) 319 } 320 321 // StopPeerGracefully disconnect from a peer gracefully. 322 func (sw *Switch) StopPeerGracefully(peerID string) { 323 if peer := sw.peers.Get(peerID); peer != nil { 324 sw.stopAndRemovePeer(peer, nil) 325 } 326 } 327 328 func (sw *Switch) addPeerWithConnection(conn net.Conn) error { 329 peerConn, err := newInboundPeerConn(conn, sw.nodePrivKey, sw.Config.P2P) 330 if err != nil { 331 if err := conn.Close(); err != nil { 332 log.WithFields(log.Fields{"module": logModule, "remote peer:": conn.RemoteAddr().String(), " err:": err}).Warn("closes connection err") 333 } 334 return err 335 } 336 337 if err = sw.AddPeer(peerConn, false); err != nil { 338 if err := conn.Close(); err != nil { 339 log.WithFields(log.Fields{"module": logModule, "remote peer:": conn.RemoteAddr().String(), " err:": err}).Warn("closes connection err") 340 } 341 return err 342 } 343 344 log.WithFields(log.Fields{"module": logModule, "address": conn.RemoteAddr().String(), "peer num": sw.peers.Size()}).Debug("add inbound peer") 345 return nil 346 } 347 348 func (sw *Switch) connectLANPeers(lanPeer mdns.LANPeerEvent) { 349 lanPeers, _, _, numDialing := sw.NumPeers() 350 numToDial := maxNumLANPeers - lanPeers 351 log.WithFields(log.Fields{"module": logModule, "numDialing": numDialing, "numToDial": numToDial}).Debug("connect LAN peers") 352 if numToDial <= 0 { 353 return 354 } 355 addresses := make([]*NetAddress, 0) 356 for i := 0; i < len(lanPeer.IP); i++ { 357 addresses = append(addresses, NewLANNetAddressIPPort(lanPeer.IP[i], uint16(lanPeer.Port))) 358 } 359 sw.dialPeers(addresses) 360 } 361 362 func (sw *Switch) connectLANPeersRoutine() { 363 if !sw.Config.P2P.LANDiscover { 364 return 365 } 366 367 lanPeerEventSub, err := sw.lanDiscv.Subscribe() 368 if err != nil { 369 log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("subscribe LAN Peer Event error") 370 return 371 } 372 373 for { 374 select { 375 case obj, ok := <-lanPeerEventSub.Chan(): 376 if !ok { 377 log.WithFields(log.Fields{"module": logModule}).Warning("LAN peer event subscription channel closed") 378 return 379 } 380 LANPeer, ok := obj.Data.(mdns.LANPeerEvent) 381 if !ok { 382 log.WithFields(log.Fields{"module": logModule}).Error("event type error") 383 continue 384 } 385 sw.connectLANPeers(LANPeer) 386 case <-sw.Quit: 387 return 388 } 389 } 390 } 391 392 func (sw *Switch) listenerRoutine(l Listener) { 393 for { 394 inConn, ok := <-l.Connections() 395 if !ok { 396 break 397 } 398 399 // disconnect if we alrady have MaxNumPeers 400 if sw.peers.Size() >= sw.Config.P2P.MaxNumPeers { 401 if err := inConn.Close(); err != nil { 402 log.WithFields(log.Fields{"module": logModule, "remote peer:": inConn.RemoteAddr().String(), " err:": err}).Warn("closes connection err") 403 } 404 log.Info("Ignoring inbound connection: already have enough peers.") 405 continue 406 } 407 408 // New inbound connection! 409 if err := sw.addPeerWithConnection(inConn); err != nil { 410 log.Info("Ignoring inbound connection: error while adding peer.", " address:", inConn.RemoteAddr().String(), " error:", err) 411 continue 412 } 413 } 414 } 415 416 func (sw *Switch) dialPeerWorker(a *NetAddress, wg *sync.WaitGroup) { 417 if err := sw.DialPeerWithAddress(a); err != nil { 418 log.WithFields(log.Fields{"module": logModule, "addr": a, "err": err}).Warn("dialPeerWorker fail on dial peer") 419 } 420 wg.Done() 421 } 422 423 func (sw *Switch) dialPeers(addresses []*NetAddress) { 424 connectedPeers := make(map[string]struct{}) 425 for _, peer := range sw.Peers().List() { 426 connectedPeers[peer.RemoteAddrHost()] = struct{}{} 427 } 428 429 var wg sync.WaitGroup 430 for _, address := range addresses { 431 if sw.NodeInfo().ListenAddr == address.String() { 432 continue 433 } 434 if dialling := sw.IsDialing(address); dialling { 435 continue 436 } 437 if _, ok := connectedPeers[address.IP.String()]; ok { 438 continue 439 } 440 441 wg.Add(1) 442 go sw.dialPeerWorker(address, &wg) 443 } 444 wg.Wait() 445 } 446 447 func (sw *Switch) ensureKeepConnectPeers() { 448 keepDials := netutil.CheckAndSplitAddresses(sw.Config.P2P.KeepDial) 449 addresses := make([]*NetAddress, 0) 450 for _, keepDial := range keepDials { 451 address, err := NewNetAddressString(keepDial) 452 if err != nil { 453 log.WithFields(log.Fields{"module": logModule, "err": err, "address": keepDial}).Warn("parse address to NetAddress") 454 continue 455 } 456 addresses = append(addresses, address) 457 } 458 459 sw.dialPeers(addresses) 460 } 461 462 func (sw *Switch) ensureOutboundPeers() { 463 lanPeers, numOutPeers, _, numDialing := sw.NumPeers() 464 numToDial := minNumOutboundPeers - (numOutPeers + numDialing) 465 log.WithFields(log.Fields{"module": logModule, "numOutPeers": numOutPeers, "LANPeers": lanPeers, "numDialing": numDialing, "numToDial": numToDial}).Debug("ensure peers") 466 if numToDial <= 0 { 467 return 468 } 469 470 nodes := make([]*dht.Node, numToDial) 471 n := sw.discv.ReadRandomNodes(nodes) 472 addresses := make([]*NetAddress, 0) 473 for i := 0; i < n; i++ { 474 address := NewNetAddressIPPort(nodes[i].IP, nodes[i].TCP) 475 addresses = append(addresses, address) 476 } 477 sw.dialPeers(addresses) 478 } 479 480 func (sw *Switch) ensureOutboundPeersRoutine() { 481 sw.ensureKeepConnectPeers() 482 sw.ensureOutboundPeers() 483 484 ticker := time.NewTicker(10 * time.Second) 485 defer ticker.Stop() 486 487 for { 488 select { 489 case <-ticker.C: 490 sw.ensureKeepConnectPeers() 491 sw.ensureOutboundPeers() 492 case <-sw.Quit: 493 return 494 } 495 } 496 } 497 498 func (sw *Switch) startInitPeer(peer *Peer) error { 499 // spawn send/recv routines 500 if _, err := peer.Start(); err != nil { 501 log.WithFields(log.Fields{"module": logModule, "remote peer:": peer.RemoteAddr, " err:": err}).Error("init peer err") 502 } 503 504 for _, reactor := range sw.reactors { 505 if err := reactor.AddPeer(peer); err != nil { 506 return err 507 } 508 } 509 return nil 510 } 511 512 func (sw *Switch) stopAndRemovePeer(peer *Peer, reason interface{}) { 513 sw.peers.Remove(peer) 514 for _, reactor := range sw.reactors { 515 reactor.RemovePeer(peer, reason) 516 } 517 peer.Stop() 518 519 sentStatus, receivedStatus := peer.TrafficStatus() 520 log.WithFields(log.Fields{ 521 "module": logModule, 522 "address": peer.Addr().String(), 523 "reason": reason, 524 "duration": sentStatus.Duration.String(), 525 "total_sent": sentStatus.Bytes, 526 "total_received": receivedStatus.Bytes, 527 "average_sent_rate": sentStatus.AvgRate, 528 "average_received_rate": receivedStatus.AvgRate, 529 "peer num": sw.peers.Size(), 530 }).Info("disconnect with peer") 531 }