mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-23 14:24:14 -04:00
Remove peerAddress on shutdown
This commit is contained in:
parent
b416408f89
commit
ea1afdebee
8 changed files with 104 additions and 56 deletions
|
@ -17,19 +17,19 @@
|
||||||
|
|
||||||
package io.bitsquare.app;
|
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.SystemTray;
|
||||||
import io.bitsquare.gui.components.Popups;
|
import io.bitsquare.gui.components.Popups;
|
||||||
import io.bitsquare.gui.main.MainView;
|
import io.bitsquare.gui.main.MainView;
|
||||||
import io.bitsquare.gui.main.debug.DebugView;
|
import io.bitsquare.gui.main.debug.DebugView;
|
||||||
import io.bitsquare.gui.util.ImageUtil;
|
import io.bitsquare.gui.util.ImageUtil;
|
||||||
import io.bitsquare.persistence.Persistence;
|
import io.bitsquare.persistence.Persistence;
|
||||||
|
import io.bitsquare.user.AccountSettings;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import io.bitsquare.util.Utilities;
|
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;
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
@ -109,8 +109,11 @@ public class BitsquareApp extends Application {
|
||||||
|
|
||||||
// configure the system tray
|
// configure the system tray
|
||||||
|
|
||||||
SystemTray systemTray = new SystemTray(primaryStage, this::stop);
|
SystemTray.create(primaryStage, this::stop);
|
||||||
primaryStage.setOnCloseRequest(e -> stop());
|
primaryStage.setOnCloseRequest(e -> {
|
||||||
|
e.consume();
|
||||||
|
stop();
|
||||||
|
});
|
||||||
scene.setOnKeyReleased(keyEvent -> {
|
scene.setOnKeyReleased(keyEvent -> {
|
||||||
// For now we exit when closing/quit the app.
|
// 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
|
// Later we will only hide the window (systemTray.hideStage()) and use the exit item in the system tray for
|
||||||
|
|
|
@ -48,11 +48,17 @@ public class SystemTray {
|
||||||
|
|
||||||
private static final String SHOW_WINDOW_LABEL = "Show exchange window";
|
private static final String SHOW_WINDOW_LABEL = "Show exchange window";
|
||||||
private static final String HIDE_WINDOW_LABEL = "Hide exchange window";
|
private static final String HIDE_WINDOW_LABEL = "Hide exchange window";
|
||||||
|
private static SystemTray systemTray;
|
||||||
|
|
||||||
private final Stage stage;
|
private final Stage stage;
|
||||||
private final Runnable onExit;
|
private final Runnable onExit;
|
||||||
private final MenuItem toggleShowHideItem = new MenuItem(HIDE_WINDOW_LABEL);
|
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) {
|
public SystemTray(Stage stage, Runnable onExit) {
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
this.onExit = onExit;
|
this.onExit = onExit;
|
||||||
|
@ -126,4 +132,5 @@ public class SystemTray {
|
||||||
stage.hide();
|
stage.hide();
|
||||||
toggleShowHideItem.setLabel(SHOW_WINDOW_LABEL);
|
toggleShowHideItem.setLabel(SHOW_WINDOW_LABEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public class TomP2PNetworkModule extends NetworkModule {
|
||||||
protected void doClose(Injector injector) {
|
protected void doClose(Injector injector) {
|
||||||
super.doClose(injector);
|
super.doClose(injector);
|
||||||
|
|
||||||
|
// First shut down TomP2PNode to remove address from DHT
|
||||||
|
injector.getInstance(TomP2PNode.class).shutDown();
|
||||||
injector.getInstance(BootstrappedPeerBuilder.class).shutDown();
|
injector.getInstance(BootstrappedPeerBuilder.class).shutDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,11 +72,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
*/
|
*/
|
||||||
public class TomP2PNode implements ClientNode {
|
public class TomP2PNode implements ClientNode {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TomP2PNode.class);
|
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 KeyPair keyPair;
|
||||||
private PeerAddress storedPeerAddress;
|
private PeerAddress storedPeerAddress;
|
||||||
private PeerDHT peerDHT;
|
private PeerDHT peerDHT;
|
||||||
private BootstrappedPeerBuilder bootstrappedPeerBuilder;
|
private BootstrappedPeerBuilder bootstrappedPeerBuilder;
|
||||||
|
private Timer timerForStoreAddress;
|
||||||
|
private Timer timerForIPCheck;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -119,6 +124,7 @@ public class TomP2PNode implements ClientNode {
|
||||||
if (peerDHT != null) {
|
if (peerDHT != null) {
|
||||||
TomP2PNode.this.peerDHT = peerDHT;
|
TomP2PNode.this.peerDHT = peerDHT;
|
||||||
setupTimerForIPCheck();
|
setupTimerForIPCheck();
|
||||||
|
setupTimerForStoreAddress();
|
||||||
setupReplyHandler(messageBroker);
|
setupReplyHandler(messageBroker);
|
||||||
try {
|
try {
|
||||||
storeAddress();
|
storeAddress();
|
||||||
|
@ -143,6 +149,44 @@ public class TomP2PNode implements ClientNode {
|
||||||
return bootstrapStateSubject.asObservable();
|
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
|
// Generic DHT methods
|
||||||
|
@ -306,26 +350,44 @@ public class TomP2PNode implements ClientNode {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTimerForIPCheck() {
|
private void setupTimerForStoreAddress() {
|
||||||
Timer timer = new Timer();
|
timerForStoreAddress = new Timer();
|
||||||
long checkIfIPChangedPeriod = 600 * 1000;
|
timerForStoreAddress.scheduleAtFixedRate(new TimerTask() {
|
||||||
timer.scheduleAtFixedRate(new TimerTask() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (storedPeerAddress != null && peerDHT != null
|
if (storedPeerAddress != null && peerDHT != null && !storedPeerAddress.equals(peerDHT.peerAddress()))
|
||||||
&& !storedPeerAddress.equals(peerDHT.peerAddress()))
|
|
||||||
try {
|
try {
|
||||||
storeAddress();
|
storeAddress();
|
||||||
} catch (NetworkException e) {
|
} catch (NetworkException e) {
|
||||||
e.printStackTrace();
|
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 {
|
private void storeAddress() throws NetworkException {
|
||||||
try {
|
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<BaseFuture>() {
|
futurePut.addListener(new BaseFutureListener<BaseFuture>() {
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
public void operationComplete(BaseFuture future) throws Exception {
|
||||||
|
@ -335,8 +397,7 @@ public class TomP2PNode implements ClientNode {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error("storedPeerAddress not successful");
|
log.error("storedPeerAddress not successful");
|
||||||
throw new NetworkException("Storing address was not successful. Reason: "
|
throw new NetworkException("Storing address was not successful. Reason: " + future.failedReason());
|
||||||
+ 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
|
private void removeAddress() {
|
||||||
public ConnectionType getConnectionType() {
|
try {
|
||||||
BootstrapState bootstrapState = bootstrappedPeerBuilder.getBootstrapState().get();
|
Number160 locationKey = Utils.makeSHAHash(keyPair.getPublic().getEncoded());
|
||||||
switch (bootstrapState) {
|
Data data = new Data(new TomP2PPeer(peerDHT.peerAddress()));
|
||||||
case DISCOVERY_DIRECT_SUCCEEDED:
|
removeFromDataMap(locationKey, data).awaitUninterruptibly(2000); // give it max. 2 sec. to remove the address at shut down
|
||||||
return ConnectionType.DIRECT;
|
} catch (IOException e) {
|
||||||
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
e.printStackTrace();
|
||||||
return ConnectionType.MANUAL_PORT_FORWARDING;
|
log.error("Exception at removeAddress " + e.toString());
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,5 +38,5 @@ public interface TradeMessageService extends MessageBroker {
|
||||||
|
|
||||||
void removeMessageHandler(MessageHandler listener);
|
void removeMessageHandler(MessageHandler listener);
|
||||||
|
|
||||||
void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener);
|
void findPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class GetPeerAddress extends Task<CheckOfferAvailabilityModel> {
|
||||||
@Override
|
@Override
|
||||||
protected void doRun() {
|
protected void doRun() {
|
||||||
try {
|
try {
|
||||||
model.tradeMessageService.getPeerAddress(model.offer.getMessagePublicKey(), new GetPeerAddressListener() {
|
model.tradeMessageService.findPeerAddress(model.offer.getMessagePublicKey(), new GetPeerAddressListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Peer peer) {
|
public void onResult(Peer peer) {
|
||||||
model.setPeer(peer);
|
model.setPeer(peer);
|
||||||
|
|
|
@ -75,15 +75,16 @@ public class TomP2PTradeMessageService implements TradeMessageService {
|
||||||
// Find peer address by publicKey
|
// 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());
|
final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded());
|
||||||
FutureGet futureGet = tomP2PNode.getDomainProtectedData(locationKey, publicKey);
|
FutureGet futureGet = tomP2PNode.getDomainProtectedData(locationKey, publicKey);
|
||||||
|
log.trace("findPeerAddress called");
|
||||||
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(BaseFuture baseFuture) throws Exception {
|
public void operationComplete(BaseFuture baseFuture) throws Exception {
|
||||||
if (baseFuture.isSuccess() && futureGet.data() != null) {
|
if (baseFuture.isSuccess() && futureGet.data() != null) {
|
||||||
final Peer peer = (Peer) futureGet.data().object();
|
final Peer peer = (Peer) futureGet.data().object();
|
||||||
|
log.trace("Peer found in DHT. Peer = " + peer);
|
||||||
executor.execute(() -> listener.onResult(peer));
|
executor.execute(() -> listener.onResult(peer));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
||||||
|
|
||||||
<logger name="org.bitcoinj" level="TRACE"/>
|
<logger name="org.bitcoinj" level="TRACE"/>
|
||||||
<logger name="net.tomp2p" level="ERROR"/>
|
<logger name="net.tomp2p" level="INFO"/>
|
||||||
|
|
||||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||||
<logger name="org.bitcoinj.core.Peer" level="WARN"/>
|
<logger name="org.bitcoinj.core.Peer" level="WARN"/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue