mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #162 from stevemyers/master
Added built in dht seed node
This commit is contained in:
commit
0d09b2baf6
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,7 +2,7 @@
|
||||
/log
|
||||
/bin
|
||||
/out
|
||||
.idea
|
||||
.idea/*
|
||||
!.idea/copyright/Bitsquare_Affero_GPLv3.xml
|
||||
!.idea/copyright/profiles_settings.xml
|
||||
!.idea/codeStyleSettings.xml
|
||||
|
@ -30,6 +30,7 @@ repositories {
|
||||
dependencies {
|
||||
compile 'org.bitcoinj:bitcoinj-core:0.12'
|
||||
compile 'net.tomp2p:tomp2p-all:5.0-Alpha24.805623c-SNAPSHOT'
|
||||
compile 'com.typesafe.akka:akka-actor_2.10:2.3.4'
|
||||
compile 'org.slf4j:slf4j-api:1.7.7'
|
||||
compile 'ch.qos.logback:logback-core:1.1.2'
|
||||
compile 'ch.qos.logback:logback-classic:1.1.2'
|
||||
|
@ -48,6 +48,7 @@ import javafx.stage.Stage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import akka.actor.ActorSystem;
|
||||
import lighthouse.files.AppDirectory;
|
||||
|
||||
public class BitSquare extends Application {
|
||||
@ -118,11 +119,11 @@ public class BitSquare extends Application {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
// currently there is not SystemTray support for java fx (planned for version 3) so we use the old AWT
|
||||
AWTSystemTray.createSystemTray(primaryStage);
|
||||
|
||||
final Injector injector = Guice.createInjector(new BitSquareModule());
|
||||
|
||||
// currently there is not SystemTray support for java fx (planned for version 3) so we use the old AWT
|
||||
AWTSystemTray.createSystemTray(primaryStage, injector.getInstance(ActorSystem.class));
|
||||
|
||||
walletFacade = injector.getInstance(WalletFacade.class);
|
||||
messageFacade = injector.getInstance(MessageFacade.class);
|
||||
Profiler.printMsgWithTime("BitSquare: messageFacade, walletFacade created");
|
||||
|
@ -18,6 +18,7 @@
|
||||
package io.bitsquare.di;
|
||||
|
||||
|
||||
import io.bitsquare.BitSquare;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
@ -32,9 +33,11 @@ import io.bitsquare.gui.util.validation.FiatValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.gui.util.validation.PasswordValidator;
|
||||
import io.bitsquare.msg.BootstrappedPeerFactory;
|
||||
import io.bitsquare.msg.DHTSeedService;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.P2PNode;
|
||||
import io.bitsquare.msg.SeedNodeAddress;
|
||||
import io.bitsquare.msg.actor.DHTManager;
|
||||
import io.bitsquare.persistence.Persistence;
|
||||
import io.bitsquare.settings.Settings;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
@ -55,6 +58,8 @@ import java.util.Properties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import akka.actor.ActorSystem;
|
||||
|
||||
public class BitSquareModule extends AbstractModule {
|
||||
private static final Logger log = LoggerFactory.getLogger(BitSquareModule.class);
|
||||
|
||||
@ -95,6 +100,11 @@ public class BitSquareModule extends AbstractModule {
|
||||
|
||||
bind(SeedNodeAddress.StaticSeedNodeAddresses.class).annotatedWith(Names.named("defaultSeedNode"))
|
||||
.toProvider(StaticSeedNodeAddressesProvider.class).asEagerSingleton();
|
||||
|
||||
// Actor Related Classes to Inject
|
||||
bind(ActorSystem.class).toProvider(ActorSystemProvider.class).asEagerSingleton();
|
||||
|
||||
bind(DHTSeedService.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,4 +165,17 @@ class NetworkParametersProvider implements Provider<NetworkParameters> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class ActorSystemProvider implements Provider<ActorSystem> {
|
||||
|
||||
@Override
|
||||
public ActorSystem get() {
|
||||
ActorSystem system = ActorSystem.create(BitSquare.getAppName());
|
||||
|
||||
// create top level actors
|
||||
system.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME);
|
||||
|
||||
return system;
|
||||
}
|
||||
}
|
@ -23,6 +23,8 @@ import io.bitsquare.gui.util.ImageUtil;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import javafx.application.Platform;
|
||||
@ -31,6 +33,9 @@ import javafx.stage.Stage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import akka.actor.ActorSystem;
|
||||
import scala.concurrent.duration.Duration;
|
||||
|
||||
/**
|
||||
* There is no JavaFX support yet, so we need to use AWT.
|
||||
* TODO research more
|
||||
@ -40,10 +45,13 @@ public class AWTSystemTray {
|
||||
private static boolean isStageVisible = true;
|
||||
private static MenuItem showGuiItem;
|
||||
private static Stage stage;
|
||||
private static ActorSystem actorSystem;
|
||||
private static TrayIcon trayIcon;
|
||||
|
||||
public static void createSystemTray(Stage stage) {
|
||||
public static void createSystemTray(Stage stage, ActorSystem actorSystem) {
|
||||
AWTSystemTray.stage = stage;
|
||||
AWTSystemTray.actorSystem = actorSystem;
|
||||
|
||||
if (SystemTray.isSupported()) {
|
||||
// prevent exiting the app when the last window get closed
|
||||
Platform.setImplicitExit(false);
|
||||
@ -82,6 +90,15 @@ public class AWTSystemTray {
|
||||
});
|
||||
exitItem.addActionListener(e -> {
|
||||
systemTray.remove(trayIcon);
|
||||
actorSystem.shutdown();
|
||||
try {
|
||||
actorSystem.awaitTermination(Duration.create(5L, "seconds"));
|
||||
} catch (Exception ex) {
|
||||
if (ex instanceof TimeoutException)
|
||||
log.error("ActorSystem did not shutdown properly.");
|
||||
else
|
||||
log.error(ex.getMessage());
|
||||
}
|
||||
System.exit(0);
|
||||
});
|
||||
|
||||
|
@ -21,7 +21,9 @@ import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.gui.UIModel;
|
||||
import io.bitsquare.gui.util.Profiler;
|
||||
import io.bitsquare.msg.DHTSeedService;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.actor.event.PeerInitialized;
|
||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
||||
import io.bitsquare.persistence.Persistence;
|
||||
import io.bitsquare.trade.Trade;
|
||||
@ -47,6 +49,7 @@ class MainModel extends UIModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainModel.class);
|
||||
|
||||
private final User user;
|
||||
private final DHTSeedService dhtSeedService;
|
||||
private final WalletFacade walletFacade;
|
||||
private final MessageFacade messageFacade;
|
||||
private final TradeManager tradeManager;
|
||||
@ -66,9 +69,10 @@ class MainModel extends UIModel {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private MainModel(User user, WalletFacade walletFacade, MessageFacade messageFacade,
|
||||
private MainModel(User user, DHTSeedService dhtSeedService, WalletFacade walletFacade, MessageFacade messageFacade,
|
||||
TradeManager tradeManager, Persistence persistence) {
|
||||
this.user = user;
|
||||
this.dhtSeedService = dhtSeedService;
|
||||
this.walletFacade = walletFacade;
|
||||
this.messageFacade = messageFacade;
|
||||
this.tradeManager = tradeManager;
|
||||
@ -98,20 +102,30 @@ class MainModel extends UIModel {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void initBackend() {
|
||||
Profiler.printMsgWithTime("MainModel.initFacades");
|
||||
messageFacade.init(new BootstrapListener() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
messageFacadeInited = true;
|
||||
if (walletFacadeInited) onFacadesInitialised();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(Throwable throwable) {
|
||||
log.error(throwable.toString());
|
||||
dhtSeedService.setHandler(m -> {
|
||||
if (m instanceof PeerInitialized) {
|
||||
log.debug("dht seed initialized. ");
|
||||
// init messageFacade after seed node initialized
|
||||
messageFacade.init(new BootstrapListener() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
messageFacadeInited = true;
|
||||
if (walletFacadeInited) onFacadesInitialised();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(Throwable throwable) {
|
||||
log.error(throwable.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dhtSeedService.initializePeer();
|
||||
|
||||
Profiler.printMsgWithTime("MainModel.initFacades");
|
||||
|
||||
walletFacade.initialize(() -> {
|
||||
walletFacadeInited = true;
|
||||
if (messageFacadeInited)
|
||||
|
30
src/main/java/io/bitsquare/msg/DHTSeedService.java
Normal file
30
src/main/java/io/bitsquare/msg/DHTSeedService.java
Normal file
@ -0,0 +1,30 @@
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.msg.actor.DHTManager;
|
||||
import io.bitsquare.msg.actor.command.InitializePeer;
|
||||
import io.bitsquare.util.ActorService;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.tomp2p.peers.Number160;
|
||||
|
||||
import akka.actor.ActorSystem;
|
||||
|
||||
public class DHTSeedService extends ActorService {
|
||||
|
||||
private static final List<SeedNodeAddress.StaticSeedNodeAddresses> staticSedNodeAddresses = SeedNodeAddress
|
||||
.StaticSeedNodeAddresses.getAllSeedNodeAddresses();
|
||||
|
||||
@Inject
|
||||
public DHTSeedService(ActorSystem system) {
|
||||
super(system, "/user/" + DHTManager.SEED_NAME);
|
||||
}
|
||||
|
||||
public void initializePeer() {
|
||||
|
||||
// TODO hard coded seed peer config for now, should read from config properties file
|
||||
send(new InitializePeer(new Number160(5001), 5001, null));
|
||||
}
|
||||
}
|
69
src/main/java/io/bitsquare/msg/actor/DHTManager.java
Normal file
69
src/main/java/io/bitsquare/msg/actor/DHTManager.java
Normal file
@ -0,0 +1,69 @@
|
||||
package io.bitsquare.msg.actor;
|
||||
|
||||
import io.bitsquare.msg.actor.command.InitializePeer;
|
||||
import io.bitsquare.msg.actor.event.PeerInitialized;
|
||||
|
||||
import net.tomp2p.connection.Ports;
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.futures.FutureBootstrap;
|
||||
import net.tomp2p.p2p.Peer;
|
||||
import net.tomp2p.p2p.PeerBuilder;
|
||||
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.actor.Props;
|
||||
import akka.event.Logging;
|
||||
import akka.event.LoggingAdapter;
|
||||
import akka.japi.pf.ReceiveBuilder;
|
||||
|
||||
public class DHTManager extends AbstractActor {
|
||||
|
||||
public static final String PEER_NAME = "peerDhtManager";
|
||||
public static final String SEED_NAME = "seedDhtManager";
|
||||
|
||||
private final LoggingAdapter log = Logging.getLogger(context().system(), this);
|
||||
|
||||
// TODO move into app setup
|
||||
// timeout in ms
|
||||
private final Long bootstrapTimeout = 10000L;
|
||||
|
||||
public static Props getProps() {
|
||||
return Props.create(DHTManager.class);
|
||||
}
|
||||
|
||||
private Peer peer;
|
||||
private PeerDHT peerDHT;
|
||||
|
||||
public DHTManager() {
|
||||
|
||||
receive(ReceiveBuilder
|
||||
.match(InitializePeer.class, ip -> {
|
||||
log.debug("Received message: {}", ip);
|
||||
|
||||
peer = new PeerBuilder(ip.getPeerId())
|
||||
.ports(ip.getPort() != null ? ip.getPort() : new Ports().tcpPort()).start();
|
||||
peerDHT = new PeerBuilderDHT(peer).start();
|
||||
|
||||
// TODO add code to discover non-local peers
|
||||
// FutureDiscover futureDiscover = peer.discover().peerAddress(bootstrapPeers.).start();
|
||||
// futureDiscover.awaitUninterruptibly();
|
||||
|
||||
if (ip.getBootstrapPeers() != null) {
|
||||
FutureBootstrap futureBootstrap = peer.bootstrap()
|
||||
.bootstrapTo(ip.getBootstrapPeers()).start();
|
||||
futureBootstrap.awaitUninterruptibly(bootstrapTimeout);
|
||||
}
|
||||
sender().tell(new PeerInitialized(peer.peerID()), self());
|
||||
})
|
||||
.matchAny(o -> log.info("received unknown message")).build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postStop() throws Exception {
|
||||
log.debug("postStop");
|
||||
peerDHT.shutdown();
|
||||
super.postStop();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package io.bitsquare.msg.actor.command;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
||||
/**
|
||||
* <p>Command to initialize TomP2P Peer.</p>
|
||||
*/
|
||||
public class InitializePeer {
|
||||
|
||||
private final Number160 peerId;
|
||||
private final Integer port;
|
||||
private final Collection<PeerAddress> bootstrapPeers;
|
||||
|
||||
public InitializePeer(Number160 peerId, Integer port, Collection<PeerAddress> bootstrapPeers) {
|
||||
this.peerId = peerId;
|
||||
this.port = port;
|
||||
this.bootstrapPeers = bootstrapPeers;
|
||||
}
|
||||
|
||||
public Number160 getPeerId() {
|
||||
return peerId;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public Collection<PeerAddress> getBootstrapPeers() {
|
||||
return bootstrapPeers;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package io.bitsquare.msg.actor.event;
|
||||
|
||||
|
||||
import net.tomp2p.peers.Number160;
|
||||
|
||||
/**
|
||||
* <p>TomP2P Peer Initialized event.</p>
|
||||
*/
|
||||
public class PeerInitialized {
|
||||
|
||||
private final Number160 peerId;
|
||||
|
||||
public PeerInitialized(Number160 peerId) {
|
||||
this.peerId = peerId;
|
||||
}
|
||||
|
||||
public Number160 getPeerId() {
|
||||
return peerId;
|
||||
}
|
||||
|
||||
}
|
89
src/main/java/io/bitsquare/util/ActorService.java
Normal file
89
src/main/java/io/bitsquare/util/ActorService.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util;
|
||||
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
import akka.actor.ActorSelection;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.actor.Inbox;
|
||||
import akka.event.Logging;
|
||||
import akka.event.LoggingAdapter;
|
||||
import com.sun.glass.ui.Application;
|
||||
import scala.concurrent.duration.FiniteDuration;
|
||||
|
||||
public abstract class ActorService extends Service<String> {
|
||||
|
||||
private final LoggingAdapter log;
|
||||
|
||||
private final ActorSystem system;
|
||||
private final Inbox inbox;
|
||||
private ActorSelection actor;
|
||||
|
||||
private MessageHandler handler;
|
||||
|
||||
protected ActorService(ActorSystem system, String actorPath) {
|
||||
this.log = Logging.getLogger(system, this);
|
||||
this.system = system;
|
||||
this.inbox = Inbox.create(system);
|
||||
this.actor = system.actorSelection(actorPath);
|
||||
log.debug(actor.pathString());
|
||||
this.start();
|
||||
}
|
||||
|
||||
public void setHandler(MessageHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public void send(Object command) {
|
||||
if (actor != null) {
|
||||
actor.tell(command, inbox.getRef());
|
||||
}
|
||||
}
|
||||
|
||||
protected Task<String> createTask() {
|
||||
|
||||
return new Task<String>() {
|
||||
protected String call() throws Exception {
|
||||
|
||||
while (!isCancelled()) {
|
||||
if (inbox != null) {
|
||||
try {
|
||||
Object result = inbox.receive(FiniteDuration.create(1l, "minute"));
|
||||
if (result != null) {
|
||||
System.out.println(result.toString());
|
||||
if (handler != null) {
|
||||
Application.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handler.handle(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//System.out.println(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
24
src/main/java/io/bitsquare/util/MessageHandler.java
Normal file
24
src/main/java/io/bitsquare/util/MessageHandler.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util;
|
||||
|
||||
public interface MessageHandler {
|
||||
|
||||
public void handle(Object message);
|
||||
|
||||
}
|
17
src/main/resources/application.conf
Normal file
17
src/main/resources/application.conf
Normal file
@ -0,0 +1,17 @@
|
||||
akka {
|
||||
|
||||
# Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
|
||||
# to STDOUT)
|
||||
#loggers = ["akka.event.slf4j.Slf4jLogger"]
|
||||
|
||||
# Log level used by the configured loggers (see "loggers") as soon
|
||||
# as they have been started; before that, see "stdout-loglevel"
|
||||
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||
loglevel = "DEBUG"
|
||||
|
||||
# Log level for the very basic logger activated during ActorSystem startup.
|
||||
# This logger prints the log messages to stdout (System.out).
|
||||
# Options: OFF, ERROR, WARNING, INFO, DEBUG
|
||||
stdout-loglevel = "DEBUG"
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user