forked from cerc-io/plugeth
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
|
||
|
}
|
||
|
}
|