diff options
author | obscuren <geffobscura@gmail.com> | 2014-10-27 18:50:50 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-10-27 18:50:50 +0800 |
commit | 797b93c98cdd8183fca58f0c1c554b0d5af26d41 (patch) | |
tree | 10de24dc414b05cdb2a57dfa37db7e3f7a7c5605 /p2p/peer_error_handler.go | |
parent | b095bd32371f02d204a4d0fbde75dc58baa7430d (diff) | |
parent | f62b6742f2189f45463c362897e9f49a11d811a2 (diff) | |
download | go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar.gz go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar.bz2 go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar.lz go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar.xz go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.tar.zst go-tangerine-797b93c98cdd8183fca58f0c1c554b0d5af26d41.zip |
Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop
Diffstat (limited to 'p2p/peer_error_handler.go')
-rw-r--r-- | p2p/peer_error_handler.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/p2p/peer_error_handler.go b/p2p/peer_error_handler.go new file mode 100644 index 000000000..ca6cae4db --- /dev/null +++ b/p2p/peer_error_handler.go @@ -0,0 +1,101 @@ +package p2p + +import ( + "net" +) + +const ( + severityThreshold = 10 +) + +type DisconnectRequest struct { + addr net.Addr + reason DiscReason +} + +type PeerErrorHandler struct { + quit chan chan bool + address net.Addr + peerDisconnect chan DisconnectRequest + severity int + peerErrorChan chan *PeerError + blacklist Blacklist +} + +func NewPeerErrorHandler(address net.Addr, peerDisconnect chan DisconnectRequest, peerErrorChan chan *PeerError, blacklist Blacklist) *PeerErrorHandler { + return &PeerErrorHandler{ + quit: make(chan chan bool), + address: address, + peerDisconnect: peerDisconnect, + peerErrorChan: peerErrorChan, + blacklist: blacklist, + } +} + +func (self *PeerErrorHandler) Start() { + go self.listen() +} + +func (self *PeerErrorHandler) Stop() { + q := make(chan bool) + self.quit <- q + <-q +} + +func (self *PeerErrorHandler) listen() { + for { + select { + case peerError, ok := <-self.peerErrorChan: + if ok { + logger.Debugf("error %v\n", peerError) + go self.handle(peerError) + } else { + return + } + case q := <-self.quit: + q <- true + return + } + } +} + +func (self *PeerErrorHandler) handle(peerError *PeerError) { + reason := DiscReason(' ') + switch peerError.Code { + case P2PVersionMismatch: + reason = DiscIncompatibleVersion + case PubkeyMissing, PubkeyInvalid: + reason = DiscInvalidIdentity + case PubkeyForbidden: + reason = DiscUselessPeer + case InvalidMsgCode, PacketTooShort, PayloadTooShort, MagicTokenMismatch, EmptyPayload, ProtocolBreach: + reason = DiscProtocolError + case PingTimeout: + reason = DiscReadTimeout + case WriteError, MiscError: + reason = DiscNetworkError + case InvalidGenesis, InvalidNetworkId, InvalidProtocolVersion: + reason = DiscSubprotocolError + default: + self.severity += self.getSeverity(peerError) + } + + if self.severity >= severityThreshold { + reason = DiscSubprotocolError + } + if reason != DiscReason(' ') { + self.peerDisconnect <- DisconnectRequest{ + addr: self.address, + reason: reason, + } + } +} + +func (self *PeerErrorHandler) getSeverity(peerError *PeerError) int { + switch peerError.Code { + case ReadError: + return 4 //tolerate 3 :) + default: + return 1 + } +} |