mirror of
https://gitlab.com/pulsechaincom/go-pulse.git
synced 2024-12-26 21:27:18 +00:00
f1d710af00
There were multiple synchronization issues in the disconnect handling, all caused by the odd special-casing of Peer.readLoop errors. Remove the special handling of read errors and make readLoop part of the Peer WaitGroup. Thanks to @Gustav-Simonsson for pointing at arrows in a diagram and playing rubber-duck.
130 lines
3.0 KiB
Go
130 lines
3.0 KiB
Go
package p2p
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
errMagicTokenMismatch = iota
|
|
errRead
|
|
errWrite
|
|
errMisc
|
|
errInvalidMsgCode
|
|
errInvalidMsg
|
|
errP2PVersionMismatch
|
|
errPubkeyInvalid
|
|
errPubkeyForbidden
|
|
errProtocolBreach
|
|
errPingTimeout
|
|
errInvalidNetworkId
|
|
errInvalidProtocolVersion
|
|
)
|
|
|
|
var errorToString = map[int]string{
|
|
errMagicTokenMismatch: "magic token mismatch",
|
|
errRead: "read error",
|
|
errWrite: "write error",
|
|
errMisc: "misc error",
|
|
errInvalidMsgCode: "invalid message code",
|
|
errInvalidMsg: "invalid message",
|
|
errP2PVersionMismatch: "P2P Version Mismatch",
|
|
errPubkeyInvalid: "public key invalid",
|
|
errPubkeyForbidden: "public key forbidden",
|
|
errProtocolBreach: "protocol Breach",
|
|
errPingTimeout: "ping timeout",
|
|
errInvalidNetworkId: "invalid network id",
|
|
errInvalidProtocolVersion: "invalid protocol version",
|
|
}
|
|
|
|
type peerError struct {
|
|
Code int
|
|
message string
|
|
}
|
|
|
|
func newPeerError(code int, format string, v ...interface{}) *peerError {
|
|
desc, ok := errorToString[code]
|
|
if !ok {
|
|
panic("invalid error code")
|
|
}
|
|
err := &peerError{code, desc}
|
|
if format != "" {
|
|
err.message += ": " + fmt.Sprintf(format, v...)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (self *peerError) Error() string {
|
|
return self.message
|
|
}
|
|
|
|
type DiscReason byte
|
|
|
|
const (
|
|
DiscRequested DiscReason = iota
|
|
DiscNetworkError
|
|
DiscProtocolError
|
|
DiscUselessPeer
|
|
DiscTooManyPeers
|
|
DiscAlreadyConnected
|
|
DiscIncompatibleVersion
|
|
DiscInvalidIdentity
|
|
DiscQuitting
|
|
DiscUnexpectedIdentity
|
|
DiscSelf
|
|
DiscReadTimeout
|
|
DiscSubprotocolError
|
|
)
|
|
|
|
var discReasonToString = [...]string{
|
|
DiscRequested: "Disconnect requested",
|
|
DiscNetworkError: "Network error",
|
|
DiscProtocolError: "Breach of protocol",
|
|
DiscUselessPeer: "Useless peer",
|
|
DiscTooManyPeers: "Too many peers",
|
|
DiscAlreadyConnected: "Already connected",
|
|
DiscIncompatibleVersion: "Incompatible P2P protocol version",
|
|
DiscInvalidIdentity: "Invalid node identity",
|
|
DiscQuitting: "Client quitting",
|
|
DiscUnexpectedIdentity: "Unexpected identity",
|
|
DiscSelf: "Connected to self",
|
|
DiscReadTimeout: "Read timeout",
|
|
DiscSubprotocolError: "Subprotocol error",
|
|
}
|
|
|
|
func (d DiscReason) String() string {
|
|
if len(discReasonToString) < int(d) {
|
|
return fmt.Sprintf("Unknown Reason(%d)", d)
|
|
}
|
|
return discReasonToString[d]
|
|
}
|
|
|
|
func (d DiscReason) Error() string {
|
|
return d.String()
|
|
}
|
|
|
|
func discReasonForError(err error) DiscReason {
|
|
if reason, ok := err.(DiscReason); ok {
|
|
return reason
|
|
}
|
|
peerError, ok := err.(*peerError)
|
|
if !ok {
|
|
return DiscSubprotocolError
|
|
}
|
|
switch peerError.Code {
|
|
case errP2PVersionMismatch:
|
|
return DiscIncompatibleVersion
|
|
case errPubkeyInvalid:
|
|
return DiscInvalidIdentity
|
|
case errPubkeyForbidden:
|
|
return DiscUselessPeer
|
|
case errInvalidMsgCode, errMagicTokenMismatch, errProtocolBreach:
|
|
return DiscProtocolError
|
|
case errPingTimeout:
|
|
return DiscReadTimeout
|
|
case errRead, errWrite:
|
|
return DiscNetworkError
|
|
default:
|
|
return DiscSubprotocolError
|
|
}
|
|
}
|