diff --git a/common/src/main/java/io/bitsquare/app/Version.java b/common/src/main/java/io/bitsquare/app/Version.java index e2c195261f..c8f83f6ed2 100644 --- a/common/src/main/java/io/bitsquare/app/Version.java +++ b/common/src/main/java/io/bitsquare/app/Version.java @@ -39,9 +39,10 @@ public class Version { public static int getP2PMessageVersion() { - // A changed NETWORK_PROTOCOL_VERSION for the serialized objects does not trigger reliable a disconnect. - // TODO investigate why, but java serialisation should be replaced anyway, so using one existing field + // TODO investigate why a changed NETWORK_PROTOCOL_VERSION for the serialized objects does not trigger + // reliable a disconnect., but java serialisation should be replaced anyway, so using one existing field // for the version is fine. + // BTC_NETWORK_ID is 0, 1 or 2, we use for changes at NETWORK_PROTOCOL_VERSION a multiplication with 10 // to avoid conflicts: // E.g. btc BTC_NETWORK_ID=1, NETWORK_PROTOCOL_VERSION=1 -> getNetworkId()=2; diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index e23dc50be9..7ef9b8b38f 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -198,7 +198,7 @@ public class WalletService { // TODO Get bitcoinj running over our tor proxy. BlockingClientManager need to be used to use the socket // from jtorproxy. To get supported it via nio / netty will be harder - if (!params.getId().equals(NetworkParameters.ID_REGTEST) && useTor) + if (useTor && params.getId().equals(NetworkParameters.ID_MAINNET)) walletAppKit.useTor(); // Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen diff --git a/network/src/main/java/io/bitsquare/p2p/network/Connection.java b/network/src/main/java/io/bitsquare/p2p/network/Connection.java index 011557a116..cbda8d7d1a 100644 --- a/network/src/main/java/io/bitsquare/p2p/network/Connection.java +++ b/network/src/main/java/io/bitsquare/p2p/network/Connection.java @@ -660,9 +660,12 @@ public class Connection implements MessageListener { messageListener.onMessage(message, connection); } - } catch (IOException | ClassNotFoundException | NoClassDefFoundError e) { + } catch (ClassNotFoundException | NoClassDefFoundError e) { reportInvalidRequest(RuleViolation.INVALID_DATA_TYPE); return; + } catch (IOException e) { + stop(); + sharedModel.handleConnectionException(e); } catch (Throwable t) { t.printStackTrace(); stop(); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeHandshake.java b/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeHandshake.java index a7e7f4b5f0..d4988ad774 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeHandshake.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeHandshake.java @@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import java.util.HashSet; import java.util.Random; import java.util.Timer; @@ -36,7 +37,7 @@ public class PeerExchangeHandshake implements MessageListener { public interface Listener { void onComplete(); - void onFault(String errorMessage); + void onFault(String errorMessage, @Nullable Connection connection); } @@ -94,7 +95,7 @@ public class PeerExchangeHandshake implements MessageListener { peerManager.shutDownConnection(nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, null); } }); @@ -103,11 +104,11 @@ public class PeerExchangeHandshake implements MessageListener { String errorMessage = "A timeout occurred at sending getPeersRequest:" + getPeersRequest + " for nodeAddress:" + nodeAddress; log.info(errorMessage + " / PeerExchangeHandshake=" + PeerExchangeHandshake.this); - + log.info("timeoutTimer called on " + this); peerManager.shutDownConnection(nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, null); }, 20, TimeUnit.SECONDS); } @@ -145,7 +146,7 @@ public class PeerExchangeHandshake implements MessageListener { peerManager.shutDownConnection(connection, CloseConnectionReason.SEND_MSG_FAILURE); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, connection); } }); @@ -158,7 +159,7 @@ public class PeerExchangeHandshake implements MessageListener { log.info("timeoutTimer called. this=" + this); peerManager.shutDownConnection(connection, CloseConnectionReason.SEND_MSG_TIMEOUT); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, connection); }, 20, TimeUnit.SECONDS); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeManager.java b/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeManager.java index e9373e6548..b1ea0c80dc 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeManager.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/PeerExchangeManager.java @@ -8,6 +8,7 @@ import io.bitsquare.p2p.Message; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.network.*; import io.bitsquare.p2p.peers.messages.peers.GetPeersRequest; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -115,10 +116,10 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener } @Override - public void onFault(String errorMessage) { + public void onFault(String errorMessage, @Nullable Connection connection) { log.trace("PeerExchangeHandshake of outbound connection failed.\n\terrorMessage={}\n\t" + "connection={}", errorMessage, connection); - peerManager.penalizeUnreachablePeer(connection); + peerManager.handleConnectionFault(connection); } }); peerExchangeHandshake.onGetPeersRequest((GetPeersRequest) message, connection); @@ -144,12 +145,12 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener } @Override - public void onFault(String errorMessage) { + public void onFault(String errorMessage, @Nullable Connection connection) { log.trace("PeerExchangeHandshake of outbound connection failed.\n\terrorMessage={}\n\t" + "nodeAddress={}", errorMessage, nodeAddress); peerExchangeHandshakeMap.remove(nodeAddress); - peerManager.penalizeUnreachablePeer(nodeAddress); + peerManager.handleConnectionFault(nodeAddress, connection); if (!shutDownInProgress) { if (!remainingNodeAddresses.isEmpty()) { log.info("There are remaining nodes available for requesting peers. " + diff --git a/network/src/main/java/io/bitsquare/p2p/peers/PeerManager.java b/network/src/main/java/io/bitsquare/p2p/peers/PeerManager.java index bed40bb502..748debd27f 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/PeerManager.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/PeerManager.java @@ -11,6 +11,7 @@ import javafx.beans.value.ChangeListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import java.io.File; import java.util.*; import java.util.concurrent.TimeUnit; @@ -80,6 +81,7 @@ public class PeerManager implements ConnectionListener, MessageListener { if (checkMaxConnectionsTimer == null && newValue != null) checkMaxConnectionsTimer = UserThread.runAfter(() -> { removeTooOldReportedPeers(); + removeTooOldPersistedPeers(); checkMaxConnections(MAX_CONNECTIONS); }, 3); }; @@ -114,17 +116,7 @@ public class PeerManager implements ConnectionListener, MessageListener { @Override public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) { connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener); - connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> { - penalizeUnreachablePeer(nodeAddress); - Optional reportedPeerOptional = reportedPeers.stream() - .filter(e -> e.nodeAddress.equals(nodeAddress)).findAny(); - if (reportedPeerOptional.isPresent()) { - ReportedPeer reportedPeer = reportedPeerOptional.get(); - reportedPeers.remove(reportedPeer); - persistedPeers.add(reportedPeer); - dbStorage.queueUpForSave(persistedPeers, 5000); - } - }); + handleConnectionFault(connection); } @Override @@ -224,21 +216,6 @@ public class PeerManager implements ConnectionListener, MessageListener { } } - private void removeTooOldReportedPeers() { - Log.traceCall(); - Set reportedPeersToRemove = reportedPeers.stream() - .filter(reportedPeer -> reportedPeer.lastActivityDate != null && - new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE) - .collect(Collectors.toSet()); - reportedPeersToRemove.forEach(this::removeReportedPeer); - - Set persistedPeersToRemove = persistedPeers.stream() - .filter(reportedPeer -> reportedPeer.lastActivityDate != null && - new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE) - .collect(Collectors.toSet()); - persistedPeersToRemove.forEach(this::removeFromPersistedPeers); - } - private void removeSuperfluousSeedNodes() { Log.traceCall(); Set allConnections = networkNode.getAllConnections(); @@ -262,9 +239,31 @@ public class PeerManager implements ConnectionListener, MessageListener { // Reported peers /////////////////////////////////////////////////////////////////////////////////////////// - private void removeReportedPeer(ReportedPeer reportedPeer) { - reportedPeers.remove(reportedPeer); + private boolean removeReportedPeer(ReportedPeer reportedPeer) { + boolean contained = reportedPeers.remove(reportedPeer); printReportedPeers(); + return contained; + } + + private ReportedPeer removeReportedPeer(NodeAddress nodeAddress) { + Optional reportedPeerOptional = reportedPeers.stream() + .filter(e -> e.nodeAddress.equals(nodeAddress)).findAny(); + if (reportedPeerOptional.isPresent()) { + ReportedPeer reportedPeer = reportedPeerOptional.get(); + reportedPeers.remove(reportedPeer); + return reportedPeer; + } else { + return null; + } + } + + private void removeTooOldReportedPeers() { + Log.traceCall(); + Set reportedPeersToRemove = reportedPeers.stream() + .filter(reportedPeer -> reportedPeer.lastActivityDate != null && + new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE) + .collect(Collectors.toSet()); + reportedPeersToRemove.forEach(this::removeReportedPeer); } public Set getReportedPeers() { @@ -358,15 +357,40 @@ public class PeerManager implements ConnectionListener, MessageListener { // Persisted peers /////////////////////////////////////////////////////////////////////////////////////////// - private void removeFromPersistedPeers(ReportedPeer reportedPeer) { + private boolean removePersistedPeer(ReportedPeer reportedPeer) { if (persistedPeers.contains(reportedPeer)) { persistedPeers.remove(reportedPeer); if (dbStorage != null) dbStorage.queueUpForSave(persistedPeers, 5000); + + return true; + } else { + return false; } } + private boolean removePersistedPeer(NodeAddress nodeAddress) { + Optional persistedPeerOptional = persistedPeers.stream() + .filter(e -> e.nodeAddress.equals(nodeAddress)).findAny(); + persistedPeerOptional.ifPresent(persistedPeer -> { + persistedPeers.remove(persistedPeer); + if (dbStorage != null) + dbStorage.queueUpForSave(persistedPeers, 5000); + }); + return persistedPeerOptional.isPresent(); + } + + private void removeTooOldPersistedPeers() { + Log.traceCall(); + Set persistedPeersToRemove = persistedPeers.stream() + .filter(reportedPeer -> reportedPeer.lastActivityDate != null && + new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE) + .collect(Collectors.toSet()); + persistedPeersToRemove.forEach(this::removePersistedPeer); + } + + public Set getPersistedPeers() { return persistedPeers; } @@ -380,25 +404,25 @@ public class PeerManager implements ConnectionListener, MessageListener { return networkNode.getNodeAddressesOfConfirmedConnections().size() >= MIN_CONNECTIONS; } - public void penalizeUnreachablePeer(Connection connection) { - connection.getPeersNodeAddressOptional().ifPresent(this::penalizeUnreachablePeer); + public void handleConnectionFault(Connection connection) { + connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> handleConnectionFault(nodeAddress, connection)); } - public void penalizeUnreachablePeer(NodeAddress nodeAddress) { + public void handleConnectionFault(NodeAddress nodeAddress, @Nullable Connection connection) { Log.traceCall("nodeAddress=" + nodeAddress); - reportedPeers.stream() - .filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress)) - .findAny() - .ifPresent(ReportedPeer::penalizeLastActivityDate); - persistedPeers.stream() - .filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress)) - .findAny() - .ifPresent(reportedPeer -> { - reportedPeer.penalizeLastActivityDate(); - dbStorage.queueUpForSave(persistedPeers, 5000); - }); + ReportedPeer reportedPeer = removeReportedPeer(nodeAddress); + if (connection != null && connection.getRuleViolation() != null) { + removePersistedPeer(nodeAddress); + } else { + if (reportedPeer != null) { + removePersistedPeer(nodeAddress); + reportedPeer.penalizeLastActivityDate(); + persistedPeers.add(reportedPeer); + dbStorage.queueUpForSave(persistedPeers, 5000); - removeTooOldReportedPeers(); + removeTooOldPersistedPeers(); + } + } } public Set getConnectedAndReportedPeers() { @@ -465,7 +489,7 @@ public class PeerManager implements ConnectionListener, MessageListener { for (int i = 0; i < diff; i++) { ReportedPeer toRemove = getAndRemoveRandomReportedPeer(list); removeReportedPeer(toRemove); - removeFromPersistedPeers(toRemove); + removePersistedPeer(toRemove); } } else { log.trace("No need to purge reported peers.\n\tWe don't have more then {} reported peers yet.", MAX_REPORTED_PEERS); diff --git a/network/src/main/java/io/bitsquare/p2p/peers/RequestDataHandshake.java b/network/src/main/java/io/bitsquare/p2p/peers/RequestDataHandshake.java index 8a79803221..5b80e357d0 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/RequestDataHandshake.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/RequestDataHandshake.java @@ -38,7 +38,7 @@ public class RequestDataHandshake implements MessageListener { public interface Listener { void onComplete(); - void onFault(String errorMessage); + void onFault(String errorMessage, @Nullable Connection connection); } @@ -105,7 +105,7 @@ public class RequestDataHandshake implements MessageListener { log.info(errorMessage); peerManager.shutDownConnection(nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, null); } }); @@ -117,7 +117,7 @@ public class RequestDataHandshake implements MessageListener { RequestDataHandshake.this); peerManager.shutDownConnection(nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, null); }, 10, TimeUnit.SECONDS); } @@ -146,7 +146,7 @@ public class RequestDataHandshake implements MessageListener { peerManager.shutDownConnection(connection, CloseConnectionReason.SEND_MSG_FAILURE); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, connection); } }); @@ -158,7 +158,7 @@ public class RequestDataHandshake implements MessageListener { RequestDataHandshake.this); peerManager.shutDownConnection(connection, CloseConnectionReason.SEND_MSG_TIMEOUT); shutDown(); - listener.onFault(errorMessage); + listener.onFault(errorMessage, connection); }, 10, TimeUnit.SECONDS); } diff --git a/network/src/main/java/io/bitsquare/p2p/peers/RequestDataManager.java b/network/src/main/java/io/bitsquare/p2p/peers/RequestDataManager.java index 47dea93945..0f264a1947 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/RequestDataManager.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/RequestDataManager.java @@ -9,6 +9,7 @@ import io.bitsquare.p2p.network.MessageListener; import io.bitsquare.p2p.network.NetworkNode; import io.bitsquare.p2p.peers.messages.data.GetDataRequest; import io.bitsquare.p2p.storage.P2PDataStorage; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,10 +127,10 @@ public class RequestDataManager implements MessageListener { } @Override - public void onFault(String errorMessage) { + public void onFault(String errorMessage, @Nullable Connection connection) { log.trace("requestDataHandshake of inbound connection failed.\n\tConnection={}\n\t" + "ErrorMessage={}", connection, errorMessage); - peerManager.penalizeUnreachablePeer(connection); + peerManager.handleConnectionFault(connection); } }); requestDataHandshake.onDataRequest(message, connection); @@ -171,11 +172,11 @@ public class RequestDataManager implements MessageListener { } @Override - public void onFault(String errorMessage) { + public void onFault(String errorMessage, @Nullable Connection connection) { log.trace("requestDataHandshake of outbound connection failed.\n\tnodeAddress={}\n\t" + "ErrorMessage={}", nodeAddress, errorMessage); - peerManager.penalizeUnreachablePeer(nodeAddress); + peerManager.handleConnectionFault(nodeAddress, connection); if (!shutDownInProgress) { if (!remainingNodeAddresses.isEmpty()) {