peer_error_handler.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package p2p
  2. import (
  3. "net"
  4. )
  5. const (
  6. severityThreshold = 10
  7. )
  8. type DisconnectRequest struct {
  9. addr net.Addr
  10. reason DiscReason
  11. }
  12. type PeerErrorHandler struct {
  13. quit chan chan bool
  14. address net.Addr
  15. peerDisconnect chan DisconnectRequest
  16. severity int
  17. peerErrorChan chan *PeerError
  18. blacklist Blacklist
  19. }
  20. func NewPeerErrorHandler(address net.Addr, peerDisconnect chan DisconnectRequest, peerErrorChan chan *PeerError, blacklist Blacklist) *PeerErrorHandler {
  21. return &PeerErrorHandler{
  22. quit: make(chan chan bool),
  23. address: address,
  24. peerDisconnect: peerDisconnect,
  25. peerErrorChan: peerErrorChan,
  26. blacklist: blacklist,
  27. }
  28. }
  29. func (self *PeerErrorHandler) Start() {
  30. go self.listen()
  31. }
  32. func (self *PeerErrorHandler) Stop() {
  33. q := make(chan bool)
  34. self.quit <- q
  35. <-q
  36. }
  37. func (self *PeerErrorHandler) listen() {
  38. for {
  39. select {
  40. case peerError, ok := <-self.peerErrorChan:
  41. if ok {
  42. logger.Debugf("error %v\n", peerError)
  43. go self.handle(peerError)
  44. } else {
  45. return
  46. }
  47. case q := <-self.quit:
  48. q <- true
  49. return
  50. }
  51. }
  52. }
  53. func (self *PeerErrorHandler) handle(peerError *PeerError) {
  54. reason := DiscReason(' ')
  55. switch peerError.Code {
  56. case P2PVersionMismatch:
  57. reason = DiscIncompatibleVersion
  58. case PubkeyMissing, PubkeyInvalid:
  59. reason = DiscInvalidIdentity
  60. case PubkeyForbidden:
  61. reason = DiscUselessPeer
  62. case InvalidMsgCode, PacketTooShort, PayloadTooShort, MagicTokenMismatch, EmptyPayload, ProtocolBreach:
  63. reason = DiscProtocolError
  64. case PingTimeout:
  65. reason = DiscReadTimeout
  66. case WriteError, MiscError:
  67. reason = DiscNetworkError
  68. case InvalidGenesis, InvalidNetworkId, InvalidProtocolVersion:
  69. reason = DiscSubprotocolError
  70. default:
  71. self.severity += self.getSeverity(peerError)
  72. }
  73. if self.severity >= severityThreshold {
  74. reason = DiscSubprotocolError
  75. }
  76. if reason != DiscReason(' ') {
  77. self.peerDisconnect <- DisconnectRequest{
  78. addr: self.address,
  79. reason: reason,
  80. }
  81. }
  82. }
  83. func (self *PeerErrorHandler) getSeverity(peerError *PeerError) int {
  84. switch peerError.Code {
  85. case ReadError:
  86. return 4 //tolerate 3 :)
  87. default:
  88. return 1
  89. }
  90. }