From 46344dd0b1ebcd658a17559955d5d7fdbff41630 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Wed, 21 Jan 2015 16:22:46 +0100 Subject: [PATCH] PeerGroup: fix the IPv6 routing failure detection which was broken by a recent change and improve logging in a bunch of places. --- .../org/bitcoinj/core/PeerEventListener.java | 3 ++- .../java/org/bitcoinj/core/PeerGroup.java | 20 ++++++++++++------- .../bitcoinj/net/ClientConnectionManager.java | 3 ++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/PeerEventListener.java b/core/src/main/java/org/bitcoinj/core/PeerEventListener.java index 31f4e538..a711491c 100644 --- a/core/src/main/java/org/bitcoinj/core/PeerEventListener.java +++ b/core/src/main/java/org/bitcoinj/core/PeerEventListener.java @@ -65,7 +65,8 @@ public interface PeerEventListener { /** * Called when a peer is disconnected. Note that this won't be called if the listener is registered on a * {@link PeerGroup} and the group is in the process of shutting down. If this listener is registered to a - * {@link Peer} instead of a {@link PeerGroup}, peerCount will always be 0. + * {@link Peer} instead of a {@link PeerGroup}, peerCount will always be 0. This handler can be called without + * a corresponding invocation of onPeerConnected if the initial connection is never successful. * * @param peer * @param peerCount the total number of connected peers diff --git a/core/src/main/java/org/bitcoinj/core/PeerGroup.java b/core/src/main/java/org/bitcoinj/core/PeerGroup.java index 1c911cd8..4969fe3a 100644 --- a/core/src/main/java/org/bitcoinj/core/PeerGroup.java +++ b/core/src/main/java/org/bitcoinj/core/PeerGroup.java @@ -18,6 +18,7 @@ package org.bitcoinj.core; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.*; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; @@ -1169,10 +1170,15 @@ public class PeerGroup implements TransactionBroadcaster { pendingPeers.add(peer); try { - channels.openConnection(address.toSocketAddress(), peer); - } catch (Exception e) { - log.warn("Failed to connect to " + address + ": " + e.getMessage()); - handlePeerDeath(peer, e); + log.info("Attempting connection to {} ({} connected, {} pending, {} max)", address, + peers.size(), pendingPeers.size(), maxConnections); + ListenableFuture future = channels.openConnection(address.toSocketAddress(), peer); + if (future.isDone()) + Uninterruptibles.getUninterruptibly(future); + } catch (ExecutionException e) { + Throwable cause = Throwables.getRootCause(e); + log.warn("Failed to connect to " + address + ": " + cause.getMessage()); + handlePeerDeath(peer, cause); return null; } peer.setSocketTimeout(connectTimeoutMillis); @@ -1245,10 +1251,10 @@ public class PeerGroup implements TransactionBroadcaster { backoffMap.get(peer.getAddress()).trackSuccess(); // Sets up the newly connected peer so it can do everything it needs to. - log.info("{}: New peer", peer); pendingPeers.remove(peer); peers.add(peer); newSize = peers.size(); + log.info("{}: New peer ({} connected, {} pending, {} max)", peer, newSize, pendingPeers.size(), maxConnections); // Give the peer a filter that can be used to probabilistically drop transactions that // aren't relevant to our wallet. We may still receive some false positives, which is // OK because it helps improve wallet privacy. Old nodes will just ignore the message. @@ -1386,7 +1392,7 @@ public class PeerGroup implements TransactionBroadcaster { } } - protected void handlePeerDeath(final Peer peer, @Nullable Exception exception) { + protected void handlePeerDeath(final Peer peer, @Nullable Throwable exception) { // Peer deaths can occur during startup if a connect attempt after peer discovery aborts immediately. if (!isRunning()) return; @@ -1417,7 +1423,7 @@ public class PeerGroup implements TransactionBroadcaster { groupBackoff.trackFailure(); - if (!(exception instanceof NoRouteToHostException)) { + if (exception instanceof NoRouteToHostException) { if (address.getAddr() instanceof Inet6Address && !ipv6Unreachable) { ipv6Unreachable = true; log.warn("IPv6 peer connect failed due to routing failure, ignoring IPv6 addresses from now on"); diff --git a/core/src/main/java/org/bitcoinj/net/ClientConnectionManager.java b/core/src/main/java/org/bitcoinj/net/ClientConnectionManager.java index e4dd5a77..8027023d 100644 --- a/core/src/main/java/org/bitcoinj/net/ClientConnectionManager.java +++ b/core/src/main/java/org/bitcoinj/net/ClientConnectionManager.java @@ -30,7 +30,8 @@ import java.net.SocketAddress; */ public interface ClientConnectionManager extends Service { /** - * Creates a new connection to the given address, with the given parser used to handle incoming data. + * Creates a new connection to the given address, with the given parser used to handle incoming data. Any errors + * that occur during connection will be returned in the given future, including errors that can occur immediately. */ ListenableFuture openConnection(SocketAddress serverAddress, StreamParser parser);