diff --git a/build.gradle b/build.gradle index f51fc9438f..41e6267681 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ sourceSets.main.resources.srcDirs += 'src/main/java' javafx { appID 'Bitsquare' appName 'Bitsquare' - mainClass 'io.bitsquare.BitSquare' + mainClass 'io.bitsquare.BitSquareUI' profiles { windows { @@ -41,6 +41,7 @@ dependencies { compile 'com.google.code.findbugs:jsr305:2.0.3' compile 'net.jcip:jcip-annotations:1.0' compile 'org.jetbrains:annotations:13.0' + compile 'net.sourceforge.argparse4j:argparse4j:0.4.4' testCompile 'junit:junit:4.11' testCompile 'org.mockito:mockito-all:1.9.5' } diff --git a/src/main/java/io/bitsquare/BitSquare.java b/src/main/java/io/bitsquare/BitSquare.java index fef69e3335..e3801fb7ec 100644 --- a/src/main/java/io/bitsquare/BitSquare.java +++ b/src/main/java/io/bitsquare/BitSquare.java @@ -17,185 +17,93 @@ package io.bitsquare; -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.di.BitSquareModule; -import io.bitsquare.gui.AWTSystemTray; -import io.bitsquare.gui.Navigation; -import io.bitsquare.gui.components.Popups; -import io.bitsquare.gui.util.ImageUtil; -import io.bitsquare.gui.util.Profiler; -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.msg.SeedNodeAddress; -import io.bitsquare.persistence.Persistence; -import io.bitsquare.settings.Settings; -import io.bitsquare.user.User; -import io.bitsquare.util.ViewLoader; +import io.bitsquare.msg.actor.DHTManager; +import io.bitsquare.msg.actor.command.InitializePeer; +import io.bitsquare.msg.actor.event.PeerInitialized; +import io.bitsquare.util.BitsquareArgumentParser; -import com.google.common.base.Throwables; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -import java.io.IOException; - -import java.util.Arrays; -import java.util.List; +import java.util.concurrent.TimeoutException; import javafx.application.Application; -import javafx.scene.*; -import javafx.scene.image.*; -import javafx.scene.input.*; -import javafx.stage.Stage; + +import net.tomp2p.peers.Number160; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import akka.actor.ActorRef; import akka.actor.ActorSystem; -import lighthouse.files.AppDirectory; +import akka.actor.Inbox; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; -public class BitSquare extends Application { - private static final Logger log = LoggerFactory.getLogger(BitSquare.class); +public class BitSquare { - public static final boolean fillFormsWithDummyData = true; - - private static String APP_NAME = "Bitsquare"; - private static Stage primaryStage; - private WalletFacade walletFacade; - private MessageFacade messageFacade; - - public static void main(String[] args) { - Profiler.init(); - Profiler.printMsgWithTime("BitSquare.main called with args " + Arrays.asList(args).toString()); - - if (args.length > 0) - APP_NAME = APP_NAME + "-" + args[0]; - - /*Thread seedNodeThread = new Thread(new Runnable() { - @Override - public void run() { - startSeedNode(); - } - }); - seedNodeThread.start();*/ - - launch(args); - } - - private static void startSeedNode() { - List staticSedNodeAddresses = SeedNodeAddress - .StaticSeedNodeAddresses.getAllSeedNodeAddresses(); - SeedNode seedNode = new SeedNode(new SeedNodeAddress(staticSedNodeAddresses.get(0))); - seedNode.setDaemon(true); - seedNode.start(); - - try { - // keep main thread up - Thread.sleep(Long.MAX_VALUE); - log.debug("Localhost seed node started"); - } catch (InterruptedException e) { - log.error(e.toString()); - } - - } - - - public static Stage getPrimaryStage() { - return primaryStage; - } + private static String appName = "Bitsquare"; public static String getAppName() { - return APP_NAME; + return appName; } - @Override - public void start(Stage primaryStage) { - Profiler.printMsgWithTime("BitSquare.start called"); - BitSquare.primaryStage = primaryStage; - - Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions - (Throwables.getRootCause(throwable))); + public static void main(String[] args) { + BitsquareArgumentParser parser = new BitsquareArgumentParser(); + Namespace namespace = null; try { - AppDirectory.initAppDir(APP_NAME); - } catch (IOException e) { - log.error(e.getMessage()); + namespace = parser.parseArgs(args); + } catch (ArgumentParserException e) { + parser.handleError(e); + System.exit(1); } + if (namespace != null) { - final Injector injector = Guice.createInjector(new BitSquareModule()); + if (namespace.getString(BitsquareArgumentParser.NAME_FLAG) != null) { + appName = appName + "-" + namespace.getString(BitsquareArgumentParser.NAME_FLAG); + } - // 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)); + Integer port = BitsquareArgumentParser.PORT_DEFAULT; + if (namespace.getString(BitsquareArgumentParser.PORT_FLAG) != null) { + port = Integer.valueOf(namespace.getString(BitsquareArgumentParser.PORT_FLAG)); + } + if (namespace.getBoolean(BitsquareArgumentParser.SEED_FLAG) == true) { + ActorSystem actorSystem = ActorSystem.create(getAppName()); - walletFacade = injector.getInstance(WalletFacade.class); - messageFacade = injector.getInstance(MessageFacade.class); - Profiler.printMsgWithTime("BitSquare: messageFacade, walletFacade created"); + ActorRef seedNode = actorSystem.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME); + Inbox inbox = Inbox.create(actorSystem); + inbox.send(seedNode, new InitializePeer(Number160.createHash("localhost"), port, null)); - // apply stored data - final User user = injector.getInstance(User.class); - final Settings settings = injector.getInstance(Settings.class); - final Persistence persistence = injector.getInstance(Persistence.class); - persistence.init(); - - User persistedUser = (User) persistence.read(user); - user.applyPersistedUser(persistedUser); - - settings.applyPersistedSettings((Settings) persistence.read(settings.getClass().getName())); - - primaryStage.setTitle("BitSquare (" + APP_NAME + ")"); - - // sometimes there is a rendering bug, see https://github.com/bitsquare/bitsquare/issues/160 - if (ImageUtil.isRetina()) - primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/images/window_icon@2x.png"))); - else - primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/images/window_icon.png"))); - - ViewLoader.setInjector(injector); - - final ViewLoader loader = - new ViewLoader(getClass().getResource(Navigation.Item.MAIN.getFxmlUrl()), false); - try { - final Parent view = loader.load(); - - final Scene scene = new Scene(view, 1000, 900); - scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm(), - getClass().getResource("/io/bitsquare/gui/images.css").toExternalForm()); - - setupCloseHandlers(primaryStage, scene); - - primaryStage.setScene(scene); - - // TODO resizing not fully supported yet - - /* primaryStage.setMinWidth(75); - primaryStage.setMinHeight(50);*/ - - primaryStage.setMinWidth(1000); - primaryStage.setMinHeight(750); - - Profiler.initScene(primaryStage.getScene()); - - primaryStage.show(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); + Thread seedNodeThread = new Thread(() -> { + Boolean quit = false; + while (!quit) { + try { + Object m = inbox.receive(FiniteDuration.create(5L, "seconds")); + if (m instanceof PeerInitialized) { + System.out.println("Seed Peer Initialized on port " + ((PeerInitialized) m).getPort + ()); + } + } catch (Exception e) { + if (!(e instanceof TimeoutException)) { + quit = true; + } + } + } + actorSystem.shutdown(); + try { + actorSystem.awaitTermination(Duration.create(5L, "seconds")); + } catch (Exception ex) { + if (ex instanceof TimeoutException) + System.out.println("ActorSystem did not shutdown properly."); + else + System.out.println(ex.getMessage()); + } + }); + seedNodeThread.start(); + } + else { + Application.launch(BitSquareUI.class, args); + } } } - - private void setupCloseHandlers(Stage primaryStage, Scene scene) { - primaryStage.setOnCloseRequest(e -> AWTSystemTray.setStageHidden()); - - KeyCodeCombination keyCodeCombination = new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN); - scene.setOnKeyReleased(keyEvent -> { - if (keyCodeCombination.match(keyEvent)) AWTSystemTray.setStageHidden(); - }); - } - - @Override - public void stop() throws Exception { - walletFacade.shutDown(); - messageFacade.shutDown(); - - super.stop(); - System.exit(0); - } } diff --git a/src/main/java/io/bitsquare/BitSquareUI.java b/src/main/java/io/bitsquare/BitSquareUI.java new file mode 100644 index 0000000000..046a1c7c5f --- /dev/null +++ b/src/main/java/io/bitsquare/BitSquareUI.java @@ -0,0 +1,161 @@ +/* + * 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 . + */ + +package io.bitsquare; + +import io.bitsquare.btc.WalletFacade; +import io.bitsquare.di.BitSquareModule; +import io.bitsquare.gui.AWTSystemTray; +import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.components.Popups; +import io.bitsquare.gui.util.ImageUtil; +import io.bitsquare.gui.util.Profiler; +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.persistence.Persistence; +import io.bitsquare.settings.Settings; +import io.bitsquare.user.User; +import io.bitsquare.util.ViewLoader; + +import com.google.common.base.Throwables; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +import java.io.IOException; + +import javafx.application.Application; +import javafx.scene.*; +import javafx.scene.image.*; +import javafx.scene.input.*; +import javafx.stage.Stage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import akka.actor.ActorSystem; +import lighthouse.files.AppDirectory; + +public class BitSquareUI extends Application { + private static final Logger log = LoggerFactory.getLogger(BitSquareUI.class); + + public static final boolean fillFormsWithDummyData = true; + + private static Injector injector; + private static Stage primaryStage; + private WalletFacade walletFacade; + private MessageFacade messageFacade; + + public void BitSquareUI() { + Profiler.init(); + } + + public static Stage getPrimaryStage() { + return primaryStage; + } + + @Override + public void start(Stage primaryStage) { + Profiler.printMsgWithTime("BitSquare.start called"); + BitSquareUI.primaryStage = primaryStage; + + Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions + (Throwables.getRootCause(throwable))); + + try { + AppDirectory.initAppDir(BitSquare.getAppName()); + } catch (IOException e) { + log.error(e.getMessage()); + } + + 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"); + + // apply stored data + final User user = injector.getInstance(User.class); + final Settings settings = injector.getInstance(Settings.class); + final Persistence persistence = injector.getInstance(Persistence.class); + persistence.init(); + + User persistedUser = (User) persistence.read(user); + user.applyPersistedUser(persistedUser); + + settings.applyPersistedSettings((Settings) persistence.read(settings.getClass().getName())); + + primaryStage.setTitle("BitSquare (" + BitSquare.getAppName() + ")"); + + // sometimes there is a rendering bug, see https://github.com/bitsquare/bitsquare/issues/160 + if (ImageUtil.isRetina()) + primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/images/window_icon@2x.png"))); + else + primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/images/window_icon.png"))); + + ViewLoader.setInjector(injector); + + final ViewLoader loader = + new ViewLoader(getClass().getResource(Navigation.Item.MAIN.getFxmlUrl()), false); + try { + final Parent view = loader.load(); + + final Scene scene = new Scene(view, 1000, 900); + scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm(), + getClass().getResource("/io/bitsquare/gui/images.css").toExternalForm()); + + setupCloseHandlers(primaryStage, scene); + + primaryStage.setScene(scene); + + // TODO resizing not fully supported yet + + primaryStage.setMinWidth(75); + primaryStage.setMinHeight(50); + + /* primaryStage.setMinWidth(1000); + primaryStage.setMinHeight(750);*/ + + Profiler.initScene(primaryStage.getScene()); + + primaryStage.show(); + } catch (IOException e) { + e.printStackTrace(); + log.error(e.getMessage()); + } + } + + private void setupCloseHandlers(Stage primaryStage, Scene scene) { + primaryStage.setOnCloseRequest(e -> AWTSystemTray.setStageHidden()); + + KeyCodeCombination keyCodeCombination = new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN); + scene.setOnKeyReleased(keyEvent -> { + if (keyCodeCombination.match(keyEvent)) AWTSystemTray.setStageHidden(); + }); + } + + @Override + public void stop() throws Exception { + walletFacade.shutDown(); + messageFacade.shutDown(); + + super.stop(); + System.exit(0); + } +} diff --git a/src/main/java/io/bitsquare/di/BitSquareModule.java b/src/main/java/io/bitsquare/di/BitSquareModule.java index c8b5aeb4e4..eacc591a28 100644 --- a/src/main/java/io/bitsquare/di/BitSquareModule.java +++ b/src/main/java/io/bitsquare/di/BitSquareModule.java @@ -119,14 +119,15 @@ class StaticSeedNodeAddressesProvider implements Provider { ActorSystem system = ActorSystem.create(BitSquare.getAppName()); // create top level actors - system.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME); + //system.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME); return system; } diff --git a/src/main/java/io/bitsquare/gui/components/Popups.java b/src/main/java/io/bitsquare/gui/components/Popups.java index 0b2215ec08..1696087907 100644 --- a/src/main/java/io/bitsquare/gui/components/Popups.java +++ b/src/main/java/io/bitsquare/gui/components/Popups.java @@ -18,6 +18,7 @@ package io.bitsquare.gui.components; import io.bitsquare.BitSquare; +import io.bitsquare.BitSquareUI; import io.bitsquare.gui.OverlayManager; import io.bitsquare.locale.BSResources; @@ -69,7 +70,7 @@ public class Popups { public static void openInfo(String masthead, String message, List actions) { Dialogs.create() - .owner(BitSquare.getPrimaryStage()) + .owner(BitSquareUI.getPrimaryStage()) .message(message) .masthead(masthead) .actions(actions) @@ -103,7 +104,7 @@ public class Popups { public static Action openConfirmPopup(String title, String masthead, String message, List actions) { return Dialogs.create() - .owner(BitSquare.getPrimaryStage()) + .owner(BitSquareUI.getPrimaryStage()) .title(title) .message(message) .masthead(masthead) @@ -135,7 +136,7 @@ public class Popups { private static void openWarningPopup(String title, String masthead, String message, List actions) { Dialogs.create() - .owner(BitSquare.getPrimaryStage()) + .owner(BitSquareUI.getPrimaryStage()) .title(title) .message(message) .masthead(masthead) @@ -167,7 +168,7 @@ public class Popups { private static Action openErrorPopup(String title, String masthead, String message, List actions) { return Dialogs.create() - .owner(BitSquare.getPrimaryStage()) + .owner(BitSquareUI.getPrimaryStage()) .title(title) .message(message) .masthead(masthead) @@ -195,7 +196,7 @@ public class Popups { } }); return Dialogs.create() - .owner(BitSquare.getPrimaryStage()) + .owner(BitSquareUI.getPrimaryStage()) .title(title) .message(message) .masthead(masthead) diff --git a/src/main/java/io/bitsquare/gui/main/MainModel.java b/src/main/java/io/bitsquare/gui/main/MainModel.java index c102fd242b..89a6ace254 100644 --- a/src/main/java/io/bitsquare/gui/main/MainModel.java +++ b/src/main/java/io/bitsquare/gui/main/MainModel.java @@ -21,9 +21,7 @@ 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; @@ -54,7 +52,6 @@ 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; @@ -73,10 +70,9 @@ class MainModel extends UIModel { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private MainModel(User user, DHTSeedService dhtSeedService, WalletFacade walletFacade, MessageFacade messageFacade, + private MainModel(User user, WalletFacade walletFacade, MessageFacade messageFacade, TradeManager tradeManager, Persistence persistence) { this.user = user; - this.dhtSeedService = dhtSeedService; this.walletFacade = walletFacade; this.messageFacade = messageFacade; this.tradeManager = tradeManager; @@ -110,29 +106,7 @@ class MainModel extends UIModel { // For testing with the serverside seednode we need the BootstrappedPeerFactory which gets started form // messageFacade.init - 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(); - - /* messageFacade.init(new BootstrapListener() { + messageFacade.init(new BootstrapListener() { @Override public void onCompleted() { messageFacadeInited = true; @@ -143,7 +117,7 @@ class MainModel extends UIModel { public void onFailed(Throwable throwable) { log.error(throwable.toString()); } - });*/ + }); Profiler.printMsgWithTime("MainModel.initFacades"); diff --git a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java index 9dc40f1061..8b6b814817 100644 --- a/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/arbitrator/ArbitratorSettingsViewCB.java @@ -18,6 +18,7 @@ package io.bitsquare.gui.main.account.arbitrator; import io.bitsquare.BitSquare; +import io.bitsquare.BitSquareUI; import io.bitsquare.gui.CachedViewCB; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrationViewCB; @@ -102,7 +103,7 @@ public class ArbitratorSettingsViewCB extends CachedViewCB { final Parent view = loader.load(); arbitratorRegistrationViewCB = loader.getController(); - final Stage rootStage = BitSquare.getPrimaryStage(); + final Stage rootStage = BitSquareUI.getPrimaryStage(); final Stage stage = new Stage(); stage.setTitle("Arbitrator"); stage.setMinWidth(800); diff --git a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java index c0cc8e1f76..8b65c1f90a 100644 --- a/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/account/content/restrictions/RestrictionsViewCB.java @@ -18,6 +18,7 @@ package io.bitsquare.gui.main.account.content.restrictions; import io.bitsquare.BitSquare; +import io.bitsquare.BitSquareUI; import io.bitsquare.arbitrator.Arbitrator; import io.bitsquare.gui.CachedViewCB; import io.bitsquare.gui.Navigation; @@ -196,7 +197,7 @@ public class RestrictionsViewCB extends CachedViewCB implements Initializable childController = loader.getController(); //childController.setParentController(this); - final Stage rootStage = BitSquare.getPrimaryStage(); + final Stage rootStage = BitSquareUI.getPrimaryStage(); final Stage stage = new Stage(); stage.setTitle("Arbitrator selection"); stage.setMinWidth(800); diff --git a/src/main/java/io/bitsquare/gui/main/help/Help.java b/src/main/java/io/bitsquare/gui/main/help/Help.java index 8cc64e7b91..d7d9263b52 100644 --- a/src/main/java/io/bitsquare/gui/main/help/Help.java +++ b/src/main/java/io/bitsquare/gui/main/help/Help.java @@ -18,6 +18,7 @@ package io.bitsquare.gui.main.help; import io.bitsquare.BitSquare; +import io.bitsquare.BitSquareUI; import java.net.MalformedURLException; import java.net.URL; @@ -49,7 +50,7 @@ public class Help { if (helpWindow == null) { helpWindow = new Stage(); helpWindow.initModality(Modality.NONE); - helpWindow.initOwner(BitSquare.getPrimaryStage()); + helpWindow.initOwner(BitSquareUI.getPrimaryStage()); webView = new WebView(); helpWindow.setScene(new Scene(webView, 800, 600)); } diff --git a/src/main/java/io/bitsquare/msg/DHTSeedService.java b/src/main/java/io/bitsquare/msg/DHTSeedService.java index c54d62d5a4..f13b223756 100644 --- a/src/main/java/io/bitsquare/msg/DHTSeedService.java +++ b/src/main/java/io/bitsquare/msg/DHTSeedService.java @@ -39,9 +39,9 @@ public class DHTSeedService extends ActorService { super(system, "/user/" + DHTManager.SEED_NAME); } - public void initializePeer() { + public void initializePeer(String id, Integer port) { // TODO hard coded seed peer config for now, should read from config properties file - send(new InitializePeer(new Number160(5001), 5001, null)); + send(new InitializePeer(Number160.createHash(id), port, null)); } } diff --git a/src/main/java/io/bitsquare/msg/SeedNodeAddress.java b/src/main/java/io/bitsquare/msg/SeedNodeAddress.java index 0469c59a84..02374a885b 100644 --- a/src/main/java/io/bitsquare/msg/SeedNodeAddress.java +++ b/src/main/java/io/bitsquare/msg/SeedNodeAddress.java @@ -55,8 +55,9 @@ public class SeedNodeAddress { /////////////////////////////////////////////////////////////////////////////////////////// public enum StaticSeedNodeAddresses { - LOCALHOST("localhost", "127.0.0.1", 5001), - DIGITAL_OCEAN("digitalocean.bitsquare.io", "188.226.179.109", 5000); + DIGITAL_OCEAN1("digitalocean1.bitsquare.io", "188.226.179.109", 5000), + DIGITAL_OCEAN2("digitalocean2.bitsquare.io", "128.199.251.106", 5000), + LOCALHOST("localhost", "127.0.0.1", 5001); private final String id; private final String ip; diff --git a/src/main/java/io/bitsquare/msg/actor/DHTManager.java b/src/main/java/io/bitsquare/msg/actor/DHTManager.java index 4495306242..2b97595f6f 100644 --- a/src/main/java/io/bitsquare/msg/actor/DHTManager.java +++ b/src/main/java/io/bitsquare/msg/actor/DHTManager.java @@ -67,12 +67,11 @@ public class DHTManager extends AbstractActor { .StaticSeedNodeAddresses.getAllSeedNodeAddresses(); SeedNodeAddress seedNodeAddress = new SeedNodeAddress(staticSedNodeAddresses.get(0)); - peer = new PeerBuilder( - Number160.createHash(seedNodeAddress.getId())).ports(seedNodeAddress.getPort - ()).start(); + peer = new PeerBuilder(ip.getPeerId()).ports(ip.getPort()) + .start(); // Need to add all features the clients will use (otherwise msg type is UNKNOWN_ID) - new PeerBuilderDHT(peer).start(); + peerDHT = new PeerBuilderDHT(peer).start(); PeerNAT nodeBehindNat = new PeerBuilderNAT(peer).start(); new RelayRPC(peer); //new PeerBuilderTracker(peer); @@ -92,11 +91,11 @@ public class DHTManager extends AbstractActor { .bootstrapTo(ip.getBootstrapPeers()).start(); futureBootstrap.awaitUninterruptibly(bootstrapTimeout); }*/ - sender().tell(new PeerInitialized(peer.peerID()), self()); + sender().tell(new PeerInitialized(peer.peerID(), ip.getPort()), self()); } catch (Throwable t) { log.info("The second instance has been started. If that happens at the first instance" + " we are in trouble... " + t.getMessage()); - sender().tell(new PeerInitialized(null), self()); + sender().tell(new PeerInitialized(null, null), self()); } }) .matchAny(o -> log.info("received unknown message")).build() diff --git a/src/main/java/io/bitsquare/msg/actor/event/PeerInitialized.java b/src/main/java/io/bitsquare/msg/actor/event/PeerInitialized.java index 8f27f1a535..82c4dd0cd0 100644 --- a/src/main/java/io/bitsquare/msg/actor/event/PeerInitialized.java +++ b/src/main/java/io/bitsquare/msg/actor/event/PeerInitialized.java @@ -26,13 +26,18 @@ import net.tomp2p.peers.Number160; public class PeerInitialized { private final Number160 peerId; + private final Integer port; - public PeerInitialized(Number160 peerId) { + public PeerInitialized(Number160 peerId, Integer port) { this.peerId = peerId; + this.port = port; } public Number160 getPeerId() { return peerId; } + public Integer getPort() { + return port; + } } diff --git a/src/main/java/io/bitsquare/util/BitsquareArgumentParser.java b/src/main/java/io/bitsquare/util/BitsquareArgumentParser.java new file mode 100644 index 0000000000..593e581fdb --- /dev/null +++ b/src/main/java/io/bitsquare/util/BitsquareArgumentParser.java @@ -0,0 +1,56 @@ +/* + * 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 . + */ + +package io.bitsquare.util; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.impl.Arguments; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; + +public class BitsquareArgumentParser { + + public static String SEED_FLAG = "seed"; + public static String PORT_FLAG = "port"; + public static Integer PORT_DEFAULT = 5000; + public static String NAME_FLAG = "name"; + + private final ArgumentParser parser; + + public BitsquareArgumentParser() { + parser = ArgumentParsers.newArgumentParser("BitSquare") + .defaultHelp(true) + .description("BitSquare decentralized bitcoin exchange."); + parser.addArgument("-s", "--" + SEED_FLAG) + .action(Arguments.storeTrue()) + .help("Start in DHT seed mode, no UI."); + parser.addArgument("-p", "--"+PORT_FLAG) + .setDefault(PORT_DEFAULT) + .help("IP port to listen on."); + parser.addArgument("-n", "--"+NAME_FLAG) + .help("Append name to application name."); + } + + public Namespace parseArgs(String... args) throws ArgumentParserException { + return parser.parseArgs(args); + } + + public void handleError(ArgumentParserException e) { + parser.handleError(e); + } +} diff --git a/src/main/java/io/bitsquare/util/ConfigLoader.java b/src/main/java/io/bitsquare/util/ConfigLoader.java index a4cc284790..0cde807aa3 100644 --- a/src/main/java/io/bitsquare/util/ConfigLoader.java +++ b/src/main/java/io/bitsquare/util/ConfigLoader.java @@ -34,20 +34,39 @@ public class ConfigLoader { private static final String configFilePath = AppDirectory.dir() + "/bitsquare.conf"; public static Properties loadConfig() { - Properties properties = new Properties(); InputStream inputStream = null; + + // load default properties from class path + Properties defaultProperties = new Properties(); + try { + InputStream is = ConfigLoader.class.getResourceAsStream("/bitsquare.properties"); + defaultProperties.load(is); + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + } + + // load properties file from config file path + Properties properties = new Properties(defaultProperties); if (new File(configFilePath).exists()) { try { inputStream = new FileInputStream(configFilePath); properties.load(inputStream); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); - } catch (IOException e2) { - e2.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); } } } diff --git a/src/main/resources/bitsquare.properties b/src/main/resources/bitsquare.properties index e69de29bb2..416874c054 100644 --- a/src/main/resources/bitsquare.properties +++ b/src/main/resources/bitsquare.properties @@ -0,0 +1,11 @@ +seed.0.id=digitalocean1.bitsquare.io +seed.0.address=188.226.179.109 +seed.0.port=5000 + +seed.1.id=digitalocean2.bitsquare.io +seed.1.address=128.199.251.106 +seed.1.port=5000 + +seed.2.id=localhost +seed.2.address=127.0.0.1 +seed.2.port=5001