diff options
author | zelig <viktor.tron@gmail.com> | 2014-10-23 23:57:54 +0800 |
---|---|---|
committer | zelig <viktor.tron@gmail.com> | 2014-10-23 23:57:54 +0800 |
commit | 771fbcc02e6d10cdf4cda2e8ec8ea23f11066feb (patch) | |
tree | 15a966dbe15e2f8388f69b396e613c7759b06f6d /p2p/peer_error_handler.go | |
parent | 119c5b40a7ed1aea1c871c0cb56956b8ef9303d9 (diff) | |
download | dexon-771fbcc02e6d10cdf4cda2e8ec8ea23f11066feb.tar.gz dexon-771fbcc02e6d10cdf4cda2e8ec8ea23f11066feb.tar.zst dexon-771fbcc02e6d10cdf4cda2e8ec8ea23f11066feb.zip |
initial commit of p2p package
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 + } +} |