1440f9a37a
The most visible change is event-based dialing, which should be an improvement over the timer-based system that we have at the moment. The dialer gets a chance to compute new tasks whenever peers change or dials complete. This is better than checking peers on a timer because dials happen faster. The dialer can now make more precise decisions about whom to dial based on the peer set and we can test those decisions without actually opening any sockets. Peer management is easier to test because the tests can inject connections at checkpoints (after enc handshake, after protocol handshake). Most of the handshake stuff is now part of the RLPx code. It could be exported or move to its own package because it is no longer entangled with Server logic.
98 lines
2.0 KiB
Go
98 lines
2.0 KiB
Go
package p2p
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
errInvalidMsgCode = iota
|
|
errInvalidMsg
|
|
)
|
|
|
|
var errorToString = map[int]string{
|
|
errInvalidMsgCode: "invalid message code",
|
|
errInvalidMsg: "invalid message",
|
|
}
|
|
|
|
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 uint
|
|
|
|
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 {
|
|
switch peerError.code {
|
|
case errInvalidMsgCode, errInvalidMsg:
|
|
return DiscProtocolError
|
|
default:
|
|
return DiscSubprotocolError
|
|
}
|
|
}
|
|
return DiscSubprotocolError
|
|
}
|