102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
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
|
|
}
|
|
}
|