peer_error_handler.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. errc chan error
  18. }
  19. func NewPeerErrorHandler(address net.Addr, peerDisconnect chan DisconnectRequest, errc chan error) *PeerErrorHandler {
  20. return &PeerErrorHandler{
  21. quit: make(chan chan bool),
  22. address: address,
  23. peerDisconnect: peerDisconnect,
  24. errc: errc,
  25. }
  26. }
  27. func (self *PeerErrorHandler) Start() {
  28. go self.listen()
  29. }
  30. func (self *PeerErrorHandler) Stop() {
  31. q := make(chan bool)
  32. self.quit <- q
  33. <-q
  34. }
  35. func (self *PeerErrorHandler) listen() {
  36. for {
  37. select {
  38. case err, ok := <-self.errc:
  39. if ok {
  40. logger.Debugf("error %v\n", err)
  41. go self.handle(err)
  42. } else {
  43. return
  44. }
  45. case q := <-self.quit:
  46. q <- true
  47. return
  48. }
  49. }
  50. }
  51. func (self *PeerErrorHandler) handle(err error) {
  52. reason := DiscReason(' ')
  53. peerError, ok := err.(*PeerError)
  54. if !ok {
  55. peerError = NewPeerError(MiscError, " %v", err)
  56. }
  57. switch peerError.Code {
  58. case P2PVersionMismatch:
  59. reason = DiscIncompatibleVersion
  60. case PubkeyMissing, PubkeyInvalid:
  61. reason = DiscInvalidIdentity
  62. case PubkeyForbidden:
  63. reason = DiscUselessPeer
  64. case InvalidMsgCode, PacketTooLong, PayloadTooShort, MagicTokenMismatch, ProtocolBreach:
  65. reason = DiscProtocolError
  66. case PingTimeout:
  67. reason = DiscReadTimeout
  68. case ReadError, WriteError, MiscError:
  69. reason = DiscNetworkError
  70. case InvalidGenesis, InvalidNetworkId, InvalidProtocolVersion:
  71. reason = DiscSubprotocolError
  72. default:
  73. self.severity += self.getSeverity(peerError)
  74. }
  75. if self.severity >= severityThreshold {
  76. reason = DiscSubprotocolError
  77. }
  78. if reason != DiscReason(' ') {
  79. self.peerDisconnect <- DisconnectRequest{
  80. addr: self.address,
  81. reason: reason,
  82. }
  83. }
  84. }
  85. func (self *PeerErrorHandler) getSeverity(peerError *PeerError) int {
  86. return 1
  87. }