From ea1afdebeea7d914b73d4c6e73f8e73b1cf63bf1 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Thu, 19 Mar 2015 21:12:33 +0100 Subject: [PATCH] Remove peerAddress on shutdown --- .../java/io/bitsquare/app/BitsquareApp.java | 17 ++- .../java/io/bitsquare/gui/SystemTray.java | 7 + .../network/tomp2p/TomP2PNetworkModule.java | 2 + .../bitsquare/network/tomp2p/TomP2PNode.java | 123 +++++++++++------- .../bitsquare/trade/TradeMessageService.java | 2 +- .../availability/tasks/GetPeerAddress.java | 2 +- .../tomp2p/TomP2PTradeMessageService.java | 5 +- core/src/main/resources/logback.xml | 2 +- 8 files changed, 104 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/io/bitsquare/app/BitsquareApp.java b/core/src/main/java/io/bitsquare/app/BitsquareApp.java index be2ee08d90..a7f0c8aee5 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -17,19 +17,19 @@ package io.bitsquare.app; -import io.bitsquare.user.AccountSettings; +import io.bitsquare.common.viewfx.view.CachingViewLoader; +import io.bitsquare.common.viewfx.view.View; +import io.bitsquare.common.viewfx.view.ViewLoader; +import io.bitsquare.common.viewfx.view.guice.InjectorViewFactory; import io.bitsquare.gui.SystemTray; import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.debug.DebugView; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.persistence.Persistence; +import io.bitsquare.user.AccountSettings; import io.bitsquare.user.User; import io.bitsquare.util.Utilities; -import io.bitsquare.common.viewfx.view.CachingViewLoader; -import io.bitsquare.common.viewfx.view.View; -import io.bitsquare.common.viewfx.view.ViewLoader; -import io.bitsquare.common.viewfx.view.guice.InjectorViewFactory; import com.google.common.base.Throwables; @@ -109,8 +109,11 @@ public class BitsquareApp extends Application { // configure the system tray - SystemTray systemTray = new SystemTray(primaryStage, this::stop); - primaryStage.setOnCloseRequest(e -> stop()); + SystemTray.create(primaryStage, this::stop); + primaryStage.setOnCloseRequest(e -> { + e.consume(); + stop(); + }); scene.setOnKeyReleased(keyEvent -> { // For now we exit when closing/quit the app. // Later we will only hide the window (systemTray.hideStage()) and use the exit item in the system tray for diff --git a/core/src/main/java/io/bitsquare/gui/SystemTray.java b/core/src/main/java/io/bitsquare/gui/SystemTray.java index b73fea6c55..695e9525eb 100644 --- a/core/src/main/java/io/bitsquare/gui/SystemTray.java +++ b/core/src/main/java/io/bitsquare/gui/SystemTray.java @@ -48,11 +48,17 @@ public class SystemTray { private static final String SHOW_WINDOW_LABEL = "Show exchange window"; private static final String HIDE_WINDOW_LABEL = "Hide exchange window"; + private static SystemTray systemTray; private final Stage stage; private final Runnable onExit; private final MenuItem toggleShowHideItem = new MenuItem(HIDE_WINDOW_LABEL); + + public static void create(Stage stage, Runnable onExit) { + systemTray = new SystemTray(stage, onExit); + } + public SystemTray(Stage stage, Runnable onExit) { this.stage = stage; this.onExit = onExit; @@ -126,4 +132,5 @@ public class SystemTray { stage.hide(); toggleShowHideItem.setLabel(SHOW_WINDOW_LABEL); } + } diff --git a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNetworkModule.java b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNetworkModule.java index 1e3b77820b..cedc4933c0 100644 --- a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNetworkModule.java +++ b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNetworkModule.java @@ -64,6 +64,8 @@ public class TomP2PNetworkModule extends NetworkModule { protected void doClose(Injector injector) { super.doClose(injector); + // First shut down TomP2PNode to remove address from DHT + injector.getInstance(TomP2PNode.class).shutDown(); injector.getInstance(BootstrappedPeerBuilder.class).shutDown(); } } diff --git a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java index 283663b93b..92c1b298c5 100644 --- a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java +++ b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java @@ -72,11 +72,16 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class TomP2PNode implements ClientNode { private static final Logger log = LoggerFactory.getLogger(TomP2PNode.class); + private static final int IP_CHECK_PERIOD = 2 * 60 * 1000; // Cheap call if nothing changes, so set it short to 2 min. + private static final int STORE_ADDRESS_PERIOD = 5 * 60 * 1000; // Save every 5 min. + private static final int ADDRESS_TTL = STORE_ADDRESS_PERIOD * 2; // TTL 10 min. private KeyPair keyPair; private PeerAddress storedPeerAddress; private PeerDHT peerDHT; private BootstrappedPeerBuilder bootstrappedPeerBuilder; + private Timer timerForStoreAddress; + private Timer timerForIPCheck; /////////////////////////////////////////////////////////////////////////////////////////// @@ -119,6 +124,7 @@ public class TomP2PNode implements ClientNode { if (peerDHT != null) { TomP2PNode.this.peerDHT = peerDHT; setupTimerForIPCheck(); + setupTimerForStoreAddress(); setupReplyHandler(messageBroker); try { storeAddress(); @@ -143,6 +149,44 @@ public class TomP2PNode implements ClientNode { return bootstrapStateSubject.asObservable(); } + void shutDown() { + timerForIPCheck.cancel(); + timerForStoreAddress.cancel(); + removeAddress(); + } + + + @Override + public ConnectionType getConnectionType() { + BootstrapState bootstrapState = bootstrappedPeerBuilder.getBootstrapState().get(); + switch (bootstrapState) { + case DISCOVERY_DIRECT_SUCCEEDED: + return ConnectionType.DIRECT; + case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED: + return ConnectionType.MANUAL_PORT_FORWARDING; + case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED: + return ConnectionType.AUTO_PORT_FORWARDING; + case RELAY_SUCCEEDED: + return ConnectionType.RELAY; + default: + throw new BitsquareException("Invalid bootstrap state: %s", bootstrapState); + } + } + + @Override + public Node getAddress() { + PeerAddress peerAddress = peerDHT.peerBean().serverPeerAddress(); + return Node.at( + peerDHT.peerID().toString(), + peerAddress.inetAddress().getHostAddress(), + peerAddress.peerSocketAddress().tcpPort()); + } + + @Override + public Node getBootstrapNodeAddress() { + return bootstrappedPeerBuilder.getBootstrapNode(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Generic DHT methods @@ -306,26 +350,44 @@ public class TomP2PNode implements ClientNode { }); } - private void setupTimerForIPCheck() { - Timer timer = new Timer(); - long checkIfIPChangedPeriod = 600 * 1000; - timer.scheduleAtFixedRate(new TimerTask() { + private void setupTimerForStoreAddress() { + timerForStoreAddress = new Timer(); + timerForStoreAddress.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - if (storedPeerAddress != null && peerDHT != null - && !storedPeerAddress.equals(peerDHT.peerAddress())) + if (storedPeerAddress != null && peerDHT != null && !storedPeerAddress.equals(peerDHT.peerAddress())) try { storeAddress(); } catch (NetworkException e) { e.printStackTrace(); } } - }, checkIfIPChangedPeriod, checkIfIPChangedPeriod); + }, STORE_ADDRESS_PERIOD, STORE_ADDRESS_PERIOD); + } + + private void setupTimerForIPCheck() { + timerForIPCheck = new Timer(); + timerForIPCheck.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if (storedPeerAddress != null && peerDHT != null && !storedPeerAddress.equals(peerDHT.peerAddress())) + try { + storeAddress(); + } catch (NetworkException e) { + e.printStackTrace(); + } + } + }, IP_CHECK_PERIOD, IP_CHECK_PERIOD); } private void storeAddress() throws NetworkException { try { - FuturePut futurePut = saveAddress(); + Number160 locationKey = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); + Data data = new Data(new TomP2PPeer(peerDHT.peerAddress())); + // We set a short time-to-live to make getAddress checks fail fast in case if the offerer is offline and to support cheap offerbook state updates + data.ttlSeconds(ADDRESS_TTL); + log.debug("storePeerAddress " + peerDHT.peerAddress().toString()); + FuturePut futurePut = putDomainProtectedData(locationKey, data); futurePut.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture future) throws Exception { @@ -335,8 +397,7 @@ public class TomP2PNode implements ClientNode { } else { log.error("storedPeerAddress not successful"); - throw new NetworkException("Storing address was not successful. Reason: " - + future.failedReason()); + throw new NetworkException("Storing address was not successful. Reason: " + future.failedReason()); } } @@ -353,41 +414,15 @@ public class TomP2PNode implements ClientNode { } } - private FuturePut saveAddress() throws IOException { - Number160 locationKey = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); - Data data = new Data(new TomP2PPeer(peerDHT.peerAddress())); - log.debug("storePeerAddress " + peerDHT.peerAddress().toString()); - return putDomainProtectedData(locationKey, data); - } - @Override - public ConnectionType getConnectionType() { - BootstrapState bootstrapState = bootstrappedPeerBuilder.getBootstrapState().get(); - switch (bootstrapState) { - case DISCOVERY_DIRECT_SUCCEEDED: - return ConnectionType.DIRECT; - case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED: - return ConnectionType.MANUAL_PORT_FORWARDING; - case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED: - return ConnectionType.AUTO_PORT_FORWARDING; - case RELAY_SUCCEEDED: - return ConnectionType.RELAY; - default: - throw new BitsquareException("Invalid bootstrap state: %s", bootstrapState); + private void removeAddress() { + try { + Number160 locationKey = Utils.makeSHAHash(keyPair.getPublic().getEncoded()); + Data data = new Data(new TomP2PPeer(peerDHT.peerAddress())); + removeFromDataMap(locationKey, data).awaitUninterruptibly(2000); // give it max. 2 sec. to remove the address at shut down + } catch (IOException e) { + e.printStackTrace(); + log.error("Exception at removeAddress " + e.toString()); } } - - @Override - public Node getAddress() { - PeerAddress peerAddress = peerDHT.peerBean().serverPeerAddress(); - return Node.at( - peerDHT.peerID().toString(), - peerAddress.inetAddress().getHostAddress(), - peerAddress.peerSocketAddress().tcpPort()); - } - - @Override - public Node getBootstrapNodeAddress() { - return bootstrappedPeerBuilder.getBootstrapNode(); - } } diff --git a/core/src/main/java/io/bitsquare/trade/TradeMessageService.java b/core/src/main/java/io/bitsquare/trade/TradeMessageService.java index c48334a707..87900c275d 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeMessageService.java +++ b/core/src/main/java/io/bitsquare/trade/TradeMessageService.java @@ -38,5 +38,5 @@ public interface TradeMessageService extends MessageBroker { void removeMessageHandler(MessageHandler listener); - void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener); + void findPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener); } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java index b06b4545ee..2de2b55b30 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java @@ -39,7 +39,7 @@ public class GetPeerAddress extends Task { @Override protected void doRun() { try { - model.tradeMessageService.getPeerAddress(model.offer.getMessagePublicKey(), new GetPeerAddressListener() { + model.tradeMessageService.findPeerAddress(model.offer.getMessagePublicKey(), new GetPeerAddressListener() { @Override public void onResult(Peer peer) { model.setPeer(peer); diff --git a/core/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java b/core/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java index cd27ff2278..c8571a9be1 100644 --- a/core/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java +++ b/core/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java @@ -75,15 +75,16 @@ public class TomP2PTradeMessageService implements TradeMessageService { // Find peer address by publicKey /////////////////////////////////////////////////////////////////////////////////////////// - public void getPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) { + public void findPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) { final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded()); FutureGet futureGet = tomP2PNode.getDomainProtectedData(locationKey, publicKey); - + log.trace("findPeerAddress called"); futureGet.addListener(new BaseFutureAdapter() { @Override public void operationComplete(BaseFuture baseFuture) throws Exception { if (baseFuture.isSuccess() && futureGet.data() != null) { final Peer peer = (Peer) futureGet.data().object(); + log.trace("Peer found in DHT. Peer = " + peer); executor.execute(() -> listener.onResult(peer)); } else { diff --git a/core/src/main/resources/logback.xml b/core/src/main/resources/logback.xml index fef8bec188..bddbd6e9e4 100644 --- a/core/src/main/resources/logback.xml +++ b/core/src/main/resources/logback.xml @@ -34,7 +34,7 @@ - +