diff --git a/db/errors.go b/db/errors.go index d1c72fca..e67ef08f 100644 --- a/db/errors.go +++ b/db/errors.go @@ -35,6 +35,7 @@ var KnownErrors = map[string]string{ "can't assign requested address": models.NetErrorCantAssignRequestedAddress, // transient error "cannot assign requested address": models.NetErrorCantAssignRequestedAddress, // transient error "connection gated": models.NetErrorConnectionGated, // transient error + "connection closed immediately": models.NetErrorConnectionClosedImmediately, } var ErrorStr = map[string]string{} @@ -74,6 +75,7 @@ var knownErrorsPrecedence = []string{ "failed to negotiate stream multiplexer", "resource limit exceeded", "Write on stream", + "connection closed immediately", } // NetError extracts the appropriate error type from the given error. diff --git a/db/migrations/000026_add_net_errors.up.sql b/db/migrations/000026_add_net_errors.up.sql index e7d86054..206f459c 100644 --- a/db/migrations/000026_add_net_errors.up.sql +++ b/db/migrations/000026_add_net_errors.up.sql @@ -3,6 +3,7 @@ BEGIN; ALTER TYPE net_error ADD VALUE 'connection_reset_by_peer'; ALTER TYPE net_error ADD VALUE 'cant_assign_requested_address'; ALTER TYPE net_error ADD VALUE 'connection_gated'; +ALTER TYPE net_error ADD VALUE 'connection_closed_immediately'; ALTER TYPE net_error RENAME VALUE 'no_public_ip' TO 'no_ip_address'; CREATE OR REPLACE FUNCTION calc_max_failed_visits( diff --git a/db/models/boil_types.go b/db/models/boil_types.go index a836b85f..45f13971 100644 --- a/db/models/boil_types.go +++ b/db/models/boil_types.go @@ -53,28 +53,29 @@ func makeCacheKey(cols boil.Columns, nzDefaults []string) string { // Enum values for NetError const ( - NetErrorUnknown string = "unknown" - NetErrorIoTimeout string = "io_timeout" - NetErrorNoRecentNetworkActivity string = "no_recent_network_activity" - NetErrorConnectionRefused string = "connection_refused" - NetErrorProtocolNotSupported string = "protocol_not_supported" - NetErrorPeerIDMismatch string = "peer_id_mismatch" - NetErrorNoRouteToHost string = "no_route_to_host" - NetErrorNetworkUnreachable string = "network_unreachable" - NetErrorNoGoodAddresses string = "no_good_addresses" - NetErrorContextDeadlineExceeded string = "context_deadline_exceeded" - NetErrorNoIPAddress string = "no_ip_address" - NetErrorMaxDialAttemptsExceeded string = "max_dial_attempts_exceeded" - NetErrorMaddrReset string = "maddr_reset" - NetErrorStreamReset string = "stream_reset" - NetErrorHostIsDown string = "host_is_down" - NetErrorNegotiateSecurityProtocol string = "negotiate_security_protocol" - NetErrorNegotiateStreamMultiplexer string = "negotiate_stream_multiplexer" - NetErrorResourceLimitExceeded string = "resource_limit_exceeded" - NetErrorWriteOnStream string = "write_on_stream" - NetErrorConnectionResetByPeer string = "connection_reset_by_peer" - NetErrorCantAssignRequestedAddress string = "cant_assign_requested_address" - NetErrorConnectionGated string = "connection_gated" + NetErrorUnknown string = "unknown" + NetErrorIoTimeout string = "io_timeout" + NetErrorNoRecentNetworkActivity string = "no_recent_network_activity" + NetErrorConnectionRefused string = "connection_refused" + NetErrorProtocolNotSupported string = "protocol_not_supported" + NetErrorPeerIDMismatch string = "peer_id_mismatch" + NetErrorNoRouteToHost string = "no_route_to_host" + NetErrorNetworkUnreachable string = "network_unreachable" + NetErrorNoGoodAddresses string = "no_good_addresses" + NetErrorContextDeadlineExceeded string = "context_deadline_exceeded" + NetErrorNoIPAddress string = "no_ip_address" + NetErrorMaxDialAttemptsExceeded string = "max_dial_attempts_exceeded" + NetErrorMaddrReset string = "maddr_reset" + NetErrorStreamReset string = "stream_reset" + NetErrorHostIsDown string = "host_is_down" + NetErrorNegotiateSecurityProtocol string = "negotiate_security_protocol" + NetErrorNegotiateStreamMultiplexer string = "negotiate_stream_multiplexer" + NetErrorResourceLimitExceeded string = "resource_limit_exceeded" + NetErrorWriteOnStream string = "write_on_stream" + NetErrorConnectionResetByPeer string = "connection_reset_by_peer" + NetErrorCantAssignRequestedAddress string = "cant_assign_requested_address" + NetErrorConnectionGated string = "connection_gated" + NetErrorConnectionClosedImmediately string = "connection_closed_immediately" ) func AllNetError() []string { @@ -101,6 +102,7 @@ func AllNetError() []string { NetErrorConnectionResetByPeer, NetErrorCantAssignRequestedAddress, NetErrorConnectionGated, + NetErrorConnectionClosedImmediately, } } diff --git a/discv5/crawler.go b/discv5/crawler.go index 41c6840b..ee2ee6bc 100644 --- a/discv5/crawler.go +++ b/discv5/crawler.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/friendsofgo/errors" + "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/host/basic" ma "github.com/multiformats/go-multiaddr" @@ -211,26 +212,43 @@ func (c *Crawler) connect(ctx context.Context, pi peer.AddrInfo) error { } retry := 0 - maxRetries := 1 + maxRetries := 2 for { + timeout := time.Duration(c.cfg.DialTimeout.Nanoseconds() / int64(retry+1)) + + logEntry := log.WithFields(log.Fields{ + "timeout": timeout.String(), + "remoteID": dialAddrInfo.ID.String(), + "retry": retry, + "maddrs": dialAddrInfo.Addrs, + }) + logEntry.Debugln("Connecting to peer", dialAddrInfo.ID.ShortString()) + timeoutCtx, cancel := context.WithTimeout(ctx, timeout) err := c.host.Connect(timeoutCtx, dialAddrInfo) cancel() if err == nil { - return nil + if c.host.Network().Connectedness(pi.ID) != network.Connected { + err = fmt.Errorf("connection closed immediately") + } else { + return nil + } } switch true { case strings.Contains(err.Error(), db.ErrorStr[models.NetErrorNegotiateSecurityProtocol]): case strings.Contains(err.Error(), db.ErrorStr[models.NetErrorConnectionRefused]): case strings.Contains(err.Error(), db.ErrorStr[models.NetErrorConnectionResetByPeer]): + case strings.Contains(err.Error(), db.ErrorStr[models.NetErrorConnectionClosedImmediately]): default: + logEntry.WithError(err).Debugln("Failed connecting to peer", dialAddrInfo.ID.ShortString()) return err } if retry == maxRetries { + logEntry.WithError(err).Debugln("Exceeded retries connecting to peer", dialAddrInfo.ID.ShortString()) return err } diff --git a/discv5/driver_crawler.go b/discv5/driver_crawler.go index 42306467..cf512c7b 100644 --- a/discv5/driver_crawler.go +++ b/discv5/driver_crawler.go @@ -107,7 +107,7 @@ func (p PeerInfo) Addrs() []ma.Multiaddr { func (p PeerInfo) Merge(other PeerInfo) PeerInfo { p.maddrs = utils.MergeMaddrs(p.maddrs, other.maddrs) - return p // TODO: merge + return p } type CrawlDriverConfig struct {