Official Go implementation of the Bytom protocol
修订版 | a480139f4a8be097228dd3691d883a20e9e7d691 (tree) |
---|---|
时间 | 2018-04-17 14:42:36 |
作者 | Yongfeng LI <wliyongfeng@gmai...> |
Commiter | GitHub |
Merge pull request #673 from Bytom/dev
merge dev
@@ -141,7 +141,7 @@ func (sm *SyncManager) netStart() error { | ||
141 | 141 | |
142 | 142 | //Start start sync manager service |
143 | 143 | func (sm *SyncManager) Start() { |
144 | - sm.netStart() | |
144 | + go sm.netStart() | |
145 | 145 | // broadcast transactions |
146 | 146 | go sm.txBroadcastLoop() |
147 | 147 |
@@ -2,6 +2,7 @@ package netsync | ||
2 | 2 | |
3 | 3 | import ( |
4 | 4 | "reflect" |
5 | + "sync" | |
5 | 6 | "time" |
6 | 7 | |
7 | 8 | log "github.com/sirupsen/logrus" |
@@ -19,11 +20,13 @@ const ( | ||
19 | 20 | // BlockchainChannel is a channel for blocks and status updates |
20 | 21 | BlockchainChannel = byte(0x40) |
21 | 22 | protocolHandshakeTimeout = time.Second * 10 |
23 | + handshakeRetryTicker = 4 * time.Second | |
22 | 24 | ) |
23 | 25 | |
24 | 26 | var ( |
25 | 27 | //ErrProtocolHandshakeTimeout peers handshake timeout |
26 | 28 | ErrProtocolHandshakeTimeout = errors.New("Protocol handshake timeout") |
29 | + ErrStatusRequest = errors.New("Status request error") | |
27 | 30 | ) |
28 | 31 | |
29 | 32 | // Response describes the response standard. |
@@ -49,6 +52,7 @@ type ProtocolReactor struct { | ||
49 | 52 | sw *p2p.Switch |
50 | 53 | fetcher *Fetcher |
51 | 54 | peers *peerSet |
55 | + handshakeMu sync.Mutex | |
52 | 56 | |
53 | 57 | newPeerCh chan struct{} |
54 | 58 | quitReqBlockCh chan *string |
@@ -111,7 +115,13 @@ func (pr *ProtocolReactor) syncTransactions(p *peer) { | ||
111 | 115 | |
112 | 116 | // AddPeer implements Reactor by sending our state to peer. |
113 | 117 | func (pr *ProtocolReactor) AddPeer(peer *p2p.Peer) error { |
114 | - peer.Send(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}}) | |
118 | + pr.handshakeMu.Lock() | |
119 | + defer pr.handshakeMu.Unlock() | |
120 | + | |
121 | + if ok := peer.Send(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}}); !ok { | |
122 | + return ErrStatusRequest | |
123 | + } | |
124 | + retryTicker := time.Tick(handshakeRetryTicker) | |
115 | 125 | handshakeWait := time.NewTimer(protocolHandshakeTimeout) |
116 | 126 | for { |
117 | 127 | select { |
@@ -123,6 +133,10 @@ func (pr *ProtocolReactor) AddPeer(peer *p2p.Peer) error { | ||
123 | 133 | pr.newPeerCh <- struct{}{} |
124 | 134 | return nil |
125 | 135 | } |
136 | + case <-retryTicker: | |
137 | + if ok := peer.Send(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}}); !ok { | |
138 | + return ErrStatusRequest | |
139 | + } | |
126 | 140 | case <-handshakeWait.C: |
127 | 141 | return ErrProtocolHandshakeTimeout |
128 | 142 | } |
@@ -88,6 +88,13 @@ func (sm *SyncManager) synchronise() { | ||
88 | 88 | if peer == nil { |
89 | 89 | return |
90 | 90 | } |
91 | + | |
92 | + if ok := sm.Switch().Peers().Has(peer.Key); !ok { | |
93 | + log.Info("Peer disconnected") | |
94 | + sm.sw.StopPeerGracefully(peer) | |
95 | + return | |
96 | + } | |
97 | + | |
91 | 98 | if bestHeight > sm.chain.BestBlockHeight() { |
92 | 99 | log.Info("sync peer:", peer.Addr(), " height:", bestHeight) |
93 | 100 | sm.blockKeeper.BlockRequestWorker(peer.Key, bestHeight) |
@@ -409,19 +409,19 @@ FOR_LOOP: | ||
409 | 409 | // Block until .recvMonitor says we can read. |
410 | 410 | c.recvMonitor.Limit(maxMsgPacketTotalSize, atomic.LoadInt64(&c.config.RecvRate), true) |
411 | 411 | |
412 | -/* | |
413 | - // Peek into bufReader for debugging | |
414 | - if numBytes := c.bufReader.Buffered(); numBytes > 0 { | |
415 | - log.Infof("Peek connection buffer numBytes:", numBytes) | |
416 | - bytes, err := c.bufReader.Peek(cmn.MinInt(numBytes, 100)) | |
417 | - if err == nil { | |
418 | - log.Infof("bytes:", bytes) | |
412 | + /* | |
413 | + // Peek into bufReader for debugging | |
414 | + if numBytes := c.bufReader.Buffered(); numBytes > 0 { | |
415 | + log.Infof("Peek connection buffer numBytes:", numBytes) | |
416 | + bytes, err := c.bufReader.Peek(cmn.MinInt(numBytes, 100)) | |
417 | + if err == nil { | |
418 | + log.Infof("bytes:", bytes) | |
419 | + } else { | |
420 | + log.Warning("Error peeking connection buffer err:", err) | |
421 | + } | |
419 | 422 | } else { |
420 | - log.Warning("Error peeking connection buffer err:", err) | |
423 | + log.Warning("Received bytes number is:", numBytes) | |
421 | 424 | } |
422 | - } else { | |
423 | - log.Warning("Received bytes number is:", numBytes) | |
424 | - } | |
425 | 425 | */ |
426 | 426 | |
427 | 427 | // Read packet type |
@@ -5,10 +5,13 @@ import ( | ||
5 | 5 | "fmt" |
6 | 6 | "math/rand" |
7 | 7 | "reflect" |
8 | + "strings" | |
8 | 9 | "time" |
10 | + | |
9 | 11 | log "github.com/sirupsen/logrus" |
10 | 12 | wire "github.com/tendermint/go-wire" |
11 | 13 | cmn "github.com/tendermint/tmlibs/common" |
14 | + | |
12 | 15 | "github.com/bytom/errors" |
13 | 16 | ) |
14 | 17 |
@@ -244,6 +247,7 @@ func (r *PEXReactor) ensurePeers() { | ||
244 | 247 | return |
245 | 248 | } |
246 | 249 | |
250 | + newBias := cmn.MinInt(numOutPeers, 8)*10 + 10 | |
247 | 251 | toDial := make(map[string]*NetAddress) |
248 | 252 | |
249 | 253 | // Try to pick numToDial addresses to dial. |
@@ -253,7 +257,7 @@ func (r *PEXReactor) ensurePeers() { | ||
253 | 257 | // if we already have many connections. This algorithm isn't perfect, but |
254 | 258 | // it somewhat ensures that we prioritize connecting to more-vetted |
255 | 259 | // peers. |
256 | - newBias := cmn.MinInt(numOutPeers, 8)*10 + 10 | |
260 | + | |
257 | 261 | var picked *NetAddress |
258 | 262 | // Try to fetch a new peer 3 times. |
259 | 263 | // This caps the maximum number of tries to 3 * numToDial. |
@@ -265,8 +269,9 @@ func (r *PEXReactor) ensurePeers() { | ||
265 | 269 | _, alreadySelected := toDial[try.IP.String()] |
266 | 270 | alreadyDialing := r.Switch.IsDialing(try) |
267 | 271 | var alreadyConnected bool |
272 | + | |
268 | 273 | for _, v := range r.Switch.Peers().list { |
269 | - if v.mconn.RemoteAddress.String() == try.String() { | |
274 | + if strings.Compare(v.mconn.RemoteAddress.IP.String(), try.IP.String()) == 0 { | |
270 | 275 | alreadyConnected = true |
271 | 276 | break |
272 | 277 | } |
@@ -287,12 +292,9 @@ func (r *PEXReactor) ensurePeers() { | ||
287 | 292 | |
288 | 293 | // Dial picked addresses |
289 | 294 | for _, item := range toDial { |
290 | - go func(picked *NetAddress) { | |
291 | - _, err := r.Switch.DialPeerWithAddress(picked, false) | |
292 | - if err != nil { | |
293 | - r.book.MarkAttempt(picked) | |
294 | - } | |
295 | - }(item) | |
295 | + if _, err := r.Switch.DialPeerWithAddress(item, false); err != nil { | |
296 | + r.book.MarkAttempt(item) | |
297 | + } | |
296 | 298 | } |
297 | 299 | |
298 | 300 | // If we need more addresses, pick a random peer and ask for more. |
@@ -7,6 +7,7 @@ import ( | ||
7 | 7 | "net" |
8 | 8 | "sync" |
9 | 9 | "time" |
10 | + "strings" | |
10 | 11 | |
11 | 12 | log "github.com/sirupsen/logrus" |
12 | 13 | crypto "github.com/tendermint/go-crypto" |
@@ -19,8 +20,8 @@ import ( | ||
19 | 20 | ) |
20 | 21 | |
21 | 22 | const ( |
22 | - reconnectAttempts = 30 | |
23 | - reconnectInterval = 3 * time.Second | |
23 | + reconnectAttempts = 10 | |
24 | + reconnectInterval = 10 * time.Second | |
24 | 25 | |
25 | 26 | bannedPeerKey = "BannedPeer" |
26 | 27 | defaultBanDuration = time.Hour * 24 |
@@ -94,6 +95,8 @@ type Switch struct { | ||
94 | 95 | |
95 | 96 | var ( |
96 | 97 | ErrSwitchDuplicatePeer = errors.New("Duplicate peer") |
98 | + ErrConnectSelf = errors.New("Connect self") | |
99 | + ErrPeerConnected = errors.New("Peer is connected") | |
97 | 100 | ) |
98 | 101 | |
99 | 102 | func NewSwitch(config *cfg.P2PConfig, trustHistoryDB dbm.DB) *Switch { |
@@ -340,11 +343,8 @@ func (sw *Switch) DialSeeds(addrBook *AddrBook, seeds []string) error { | ||
340 | 343 | // permute the list, dial them in random order. |
341 | 344 | perm := rand.Perm(len(netAddrs)) |
342 | 345 | for i := 0; i < len(perm); i++ { |
343 | - go func(i int) { | |
344 | - time.Sleep(time.Duration(rand.Int63n(3000)) * time.Millisecond) | |
345 | - j := perm[i] | |
346 | - sw.dialSeed(netAddrs[j]) | |
347 | - }(i) | |
346 | + j := perm[i] | |
347 | + sw.dialSeed(netAddrs[j]) | |
348 | 348 | } |
349 | 349 | return nil |
350 | 350 | } |
@@ -362,7 +362,14 @@ func (sw *Switch) DialPeerWithAddress(addr *NetAddress, persistent bool) (*Peer, | ||
362 | 362 | if err := sw.checkBannedPeer(addr.IP.String()); err != nil { |
363 | 363 | return nil, err |
364 | 364 | } |
365 | - | |
365 | + if strings.Compare(addr.IP.String(), sw.nodeInfo.ListenHost()) == 0 { | |
366 | + return nil, ErrConnectSelf | |
367 | + } | |
368 | + for _, v := range sw.Peers().list { | |
369 | + if strings.Compare(v.mconn.RemoteAddress.IP.String(), addr.IP.String()) == 0 { | |
370 | + return nil, ErrPeerConnected | |
371 | + } | |
372 | + } | |
366 | 373 | sw.dialing.Set(addr.IP.String(), addr) |
367 | 374 | defer sw.dialing.Delete(addr.IP.String()) |
368 | 375 |
@@ -446,38 +453,38 @@ func (sw *Switch) StopPeerForError(peer *Peer, reason interface{}) { | ||
446 | 453 | sw.stopAndRemovePeer(peer, reason) |
447 | 454 | |
448 | 455 | if peer.IsPersistent() { |
449 | - go func() { | |
450 | - log.WithField("peer", peer).Info("Reconnecting to peer") | |
451 | - for i := 1; i < reconnectAttempts; i++ { | |
452 | - if !sw.IsRunning() { | |
453 | - return | |
454 | - } | |
456 | + log.WithField("peer", peer).Info("Reconnecting to peer") | |
457 | + for i := 1; i < reconnectAttempts; i++ { | |
458 | + if !sw.IsRunning() { | |
459 | + return | |
460 | + } | |
455 | 461 | |
456 | - peer, err := sw.DialPeerWithAddress(addr, true) | |
457 | - if err != nil { | |
458 | - if i == reconnectAttempts { | |
459 | - log.WithFields(log.Fields{ | |
460 | - "retries": i, | |
461 | - "error": err, | |
462 | - }).Info("Error reconnecting to peer. Giving up") | |
463 | - return | |
464 | - } | |
465 | - if errors.Root(err) == ErrSwitchDuplicatePeer { | |
466 | - log.WithField("error", err).Info("Error reconnecting to peer. ") | |
467 | - return | |
468 | - } | |
462 | + peer, err := sw.DialPeerWithAddress(addr, true) | |
463 | + if err != nil { | |
464 | + if i == reconnectAttempts { | |
469 | 465 | log.WithFields(log.Fields{ |
470 | 466 | "retries": i, |
471 | 467 | "error": err, |
472 | - }).Info("Error reconnecting to peer. Trying again") | |
473 | - time.Sleep(reconnectInterval) | |
474 | - continue | |
468 | + }).Info("Error reconnecting to peer. Giving up") | |
469 | + return | |
475 | 470 | } |
476 | 471 | |
477 | - log.WithField("peer", peer).Info("Reconnected to peer") | |
478 | - return | |
472 | + if errors.Root(err) == ErrConnectBannedPeer || errors.Root(err) == ErrPeerConnected || errors.Root(err) == ErrSwitchDuplicatePeer || errors.Root(err) == ErrConnectSelf { | |
473 | + log.WithField("error", err).Info("Error reconnecting to peer. ") | |
474 | + return | |
475 | + } | |
476 | + | |
477 | + log.WithFields(log.Fields{ | |
478 | + "retries": i, | |
479 | + "error": err, | |
480 | + }).Info("Error reconnecting to peer. Trying again") | |
481 | + time.Sleep(reconnectInterval) | |
482 | + continue | |
479 | 483 | } |
480 | - }() | |
484 | + | |
485 | + log.WithField("peer", peer).Info("Reconnected to peer") | |
486 | + return | |
487 | + } | |
481 | 488 | } |
482 | 489 | } |
483 | 490 |
@@ -506,6 +513,8 @@ func (sw *Switch) listenerRoutine(l Listener) { | ||
506 | 513 | // ignore connection if we already have enough |
507 | 514 | maxPeers := sw.config.MaxNumPeers |
508 | 515 | if maxPeers <= sw.peers.Size() { |
516 | + // close inConn | |
517 | + inConn.Close() | |
509 | 518 | log.WithFields(log.Fields{ |
510 | 519 | "address": inConn.RemoteAddr().String(), |
511 | 520 | "numPeers": sw.peers.Size(), |
@@ -517,6 +526,8 @@ func (sw *Switch) listenerRoutine(l Listener) { | ||
517 | 526 | // New inbound connection! |
518 | 527 | err := sw.addPeerWithConnectionAndConfig(inConn, sw.peerConfig) |
519 | 528 | if err != nil { |
529 | + // conn close for returing err | |
530 | + inConn.Close() | |
520 | 531 | log.WithFields(log.Fields{ |
521 | 532 | "address": inConn.RemoteAddr().String(), |
522 | 533 | "error": err, |
@@ -652,12 +663,10 @@ func (sw *Switch) addPeerWithConnectionAndConfig(conn net.Conn, config *PeerConf | ||
652 | 663 | |
653 | 664 | peer, err := newInboundPeerWithConfig(conn, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, sw.nodePrivKey, config) |
654 | 665 | if err != nil { |
655 | - conn.Close() | |
656 | 666 | return err |
657 | 667 | } |
658 | 668 | peer.SetLogger(sw.Logger.With("peer", conn.RemoteAddr())) |
659 | 669 | if err = sw.AddPeer(peer); err != nil { |
660 | - conn.Close() | |
661 | 670 | return err |
662 | 671 | } |
663 | 672 |