|
|
|
@ -74,14 +74,14 @@ type ProtocolManager struct { |
|
|
|
|
minedBlockSub event.Subscription |
|
|
|
|
|
|
|
|
|
// channels for fetcher, syncer, txsyncLoop
|
|
|
|
|
newPeerCh chan *peer |
|
|
|
|
txsyncCh chan *txsync |
|
|
|
|
quitSync chan struct{} |
|
|
|
|
newPeerCh chan *peer |
|
|
|
|
txsyncCh chan *txsync |
|
|
|
|
quitSync chan struct{} |
|
|
|
|
noMorePeers chan struct{} |
|
|
|
|
|
|
|
|
|
// wait group is used for graceful shutdowns during downloading
|
|
|
|
|
// and processing
|
|
|
|
|
wg sync.WaitGroup |
|
|
|
|
quit bool |
|
|
|
|
wg sync.WaitGroup |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
|
|
|
|
@ -94,16 +94,17 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, |
|
|
|
|
} |
|
|
|
|
// Create the protocol manager with the base fields
|
|
|
|
|
manager := &ProtocolManager{ |
|
|
|
|
networkId: networkId, |
|
|
|
|
fastSync: fastSync, |
|
|
|
|
eventMux: mux, |
|
|
|
|
txpool: txpool, |
|
|
|
|
blockchain: blockchain, |
|
|
|
|
chaindb: chaindb, |
|
|
|
|
peers: newPeerSet(), |
|
|
|
|
newPeerCh: make(chan *peer, 1), |
|
|
|
|
txsyncCh: make(chan *txsync), |
|
|
|
|
quitSync: make(chan struct{}), |
|
|
|
|
networkId: networkId, |
|
|
|
|
fastSync: fastSync, |
|
|
|
|
eventMux: mux, |
|
|
|
|
txpool: txpool, |
|
|
|
|
blockchain: blockchain, |
|
|
|
|
chaindb: chaindb, |
|
|
|
|
peers: newPeerSet(), |
|
|
|
|
newPeerCh: make(chan *peer), |
|
|
|
|
noMorePeers: make(chan struct{}), |
|
|
|
|
txsyncCh: make(chan *txsync), |
|
|
|
|
quitSync: make(chan struct{}), |
|
|
|
|
} |
|
|
|
|
// Initiate a sub-protocol for every implemented version we can handle
|
|
|
|
|
manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions)) |
|
|
|
@ -120,8 +121,14 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, |
|
|
|
|
Length: ProtocolLengths[i], |
|
|
|
|
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { |
|
|
|
|
peer := manager.newPeer(int(version), p, rw) |
|
|
|
|
manager.newPeerCh <- peer |
|
|
|
|
return manager.handle(peer) |
|
|
|
|
select { |
|
|
|
|
case manager.newPeerCh <- peer: |
|
|
|
|
manager.wg.Add(1) |
|
|
|
|
defer manager.wg.Done() |
|
|
|
|
return manager.handle(peer) |
|
|
|
|
case <-manager.quitSync: |
|
|
|
|
return p2p.DiscQuitting |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
NodeInfo: func() interface{} { |
|
|
|
|
return manager.NodeInfo() |
|
|
|
@ -187,16 +194,25 @@ func (pm *ProtocolManager) Start() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (pm *ProtocolManager) Stop() { |
|
|
|
|
// Showing a log message. During download / process this could actually
|
|
|
|
|
// take between 5 to 10 seconds and therefor feedback is required.
|
|
|
|
|
glog.V(logger.Info).Infoln("Stopping ethereum protocol handler...") |
|
|
|
|
|
|
|
|
|
pm.quit = true |
|
|
|
|
pm.txSub.Unsubscribe() // quits txBroadcastLoop
|
|
|
|
|
pm.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
|
|
|
|
|
close(pm.quitSync) // quits syncer, fetcher, txsyncLoop
|
|
|
|
|
|
|
|
|
|
// Wait for any process action
|
|
|
|
|
// Quit the sync loop.
|
|
|
|
|
// After this send has completed, no new peers will be accepted.
|
|
|
|
|
pm.noMorePeers <- struct{}{} |
|
|
|
|
|
|
|
|
|
// Quit fetcher, txsyncLoop.
|
|
|
|
|
close(pm.quitSync) |
|
|
|
|
|
|
|
|
|
// Disconnect existing sessions.
|
|
|
|
|
// This also closes the gate for any new registrations on the peer set.
|
|
|
|
|
// sessions which are already established but not added to pm.peers yet
|
|
|
|
|
// will exit when they try to register.
|
|
|
|
|
pm.peers.Close() |
|
|
|
|
|
|
|
|
|
// Wait for all peer handler goroutines and the loops to come down.
|
|
|
|
|
pm.wg.Wait() |
|
|
|
|
|
|
|
|
|
glog.V(logger.Info).Infoln("Ethereum protocol handler stopped") |
|
|
|
|