plugeth/p2p/peer_error_handler.go

99 lines
2.0 KiB
Go
Raw Normal View History

2014-10-23 15:57:54 +00:00
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
2014-11-04 12:21:44 +00:00
errc chan error
2014-10-23 15:57:54 +00:00
}
2014-11-04 12:21:44 +00:00
func NewPeerErrorHandler(address net.Addr, peerDisconnect chan DisconnectRequest, errc chan error) *PeerErrorHandler {
2014-10-23 15:57:54 +00:00
return &PeerErrorHandler{
quit: make(chan chan bool),
address: address,
peerDisconnect: peerDisconnect,
2014-11-04 12:21:44 +00:00
errc: errc,
2014-10-23 15:57:54 +00:00
}
}
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 {
2014-11-04 12:21:44 +00:00
case err, ok := <-self.errc:
2014-10-23 15:57:54 +00:00
if ok {
2014-11-04 12:21:44 +00:00
logger.Debugf("error %v\n", err)
go self.handle(err)
2014-10-23 15:57:54 +00:00
} else {
return
}
case q := <-self.quit:
q <- true
return
}
}
}
2014-11-04 12:21:44 +00:00
func (self *PeerErrorHandler) handle(err error) {
2014-10-23 15:57:54 +00:00
reason := DiscReason(' ')
2014-11-04 12:21:44 +00:00
peerError, ok := err.(*PeerError)
if !ok {
peerError = NewPeerError(MiscError, " %v", err)
}
2014-10-23 15:57:54 +00:00
switch peerError.Code {
case P2PVersionMismatch:
reason = DiscIncompatibleVersion
case PubkeyMissing, PubkeyInvalid:
reason = DiscInvalidIdentity
case PubkeyForbidden:
reason = DiscUselessPeer
2014-11-04 12:21:44 +00:00
case InvalidMsgCode, PacketTooLong, PayloadTooShort, MagicTokenMismatch, ProtocolBreach:
2014-10-23 15:57:54 +00:00
reason = DiscProtocolError
case PingTimeout:
reason = DiscReadTimeout
2014-11-04 12:21:44 +00:00
case ReadError, WriteError, MiscError:
2014-10-23 15:57:54 +00:00
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 {
2014-11-04 12:21:44 +00:00
return 1
2014-10-23 15:57:54 +00:00
}