mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-25 07:27:18 +01:00
Merge branch 'master'
Conflicts: src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBook.java src/main/java/io/bitsquare/msg/TomP2PMessageFacade.java
This commit is contained in:
commit
000302d29e
55 changed files with 869 additions and 709 deletions
|
@ -460,7 +460,7 @@ public class Notification {
|
|||
return onNotificationPressedProperty().get();
|
||||
}
|
||||
|
||||
private ObjectProperty<EventHandler<NotificationEvent>> onNotificationPressed = new
|
||||
private final ObjectProperty<EventHandler<NotificationEvent>> onNotificationPressed = new
|
||||
ObjectPropertyBase<EventHandler<NotificationEvent>>() {
|
||||
@Override
|
||||
public Object getBean() {
|
||||
|
@ -485,7 +485,7 @@ public class Notification {
|
|||
return onShowNotificationProperty().get();
|
||||
}
|
||||
|
||||
private ObjectProperty<EventHandler<NotificationEvent>> onShowNotification = new
|
||||
private final ObjectProperty<EventHandler<NotificationEvent>> onShowNotification = new
|
||||
ObjectPropertyBase<EventHandler<NotificationEvent>>() {
|
||||
@Override
|
||||
public Object getBean() {
|
||||
|
@ -510,7 +510,7 @@ public class Notification {
|
|||
return onHideNotificationProperty().get();
|
||||
}
|
||||
|
||||
private ObjectProperty<EventHandler<NotificationEvent>> onHideNotification = new
|
||||
private final ObjectProperty<EventHandler<NotificationEvent>> onHideNotification = new
|
||||
ObjectPropertyBase<EventHandler<NotificationEvent>>() {
|
||||
@Override
|
||||
public Object getBean() {
|
||||
|
|
|
@ -31,7 +31,7 @@ public abstract class AbstractBitsquareModule extends AbstractModule {
|
|||
|
||||
private final Set<AbstractBitsquareModule> modules = Sets.newHashSet();
|
||||
|
||||
public AbstractBitsquareModule(Properties properties) {
|
||||
protected AbstractBitsquareModule(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,41 +17,37 @@
|
|||
|
||||
package io.bitsquare.app;
|
||||
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import net.sourceforge.argparse4j.ArgumentParsers;
|
||||
import net.sourceforge.argparse4j.inf.ArgumentParserException;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
|
||||
/*
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-d PEERID, --peerid PEERID Seed peer ID. (default: digitalocean1.bitsquare.io)
|
||||
-p PORT, --port PORT IP port to listen on. (default: 5000)
|
||||
-i INTERFACE, --interface INTERFACE Network interface to listen on.
|
||||
-n NAME, --name NAME Append name to application name.
|
||||
*/
|
||||
public class ArgumentParser {
|
||||
|
||||
public static String PEER_ID_FLAG = "peerid";
|
||||
public static String PORT_FLAG = "port";
|
||||
public static Integer PORT_DEFAULT = 5000;
|
||||
public static String INFHINT_FLAG = "interface";
|
||||
public static String NAME_FLAG = "name";
|
||||
public static final String PEER_ID_FLAG = "peerid";
|
||||
public static final String PORT_FLAG = "port";
|
||||
public static final String INTERFACE_HINT_FLAG = "interface";
|
||||
public static final String NAME_FLAG = "name";
|
||||
public static final String PEER_ID_DEFAULT = BootstrapNodes.DIGITAL_OCEAN_1.getId();
|
||||
|
||||
private final net.sourceforge.argparse4j.inf.ArgumentParser parser;
|
||||
|
||||
public ArgumentParser() {
|
||||
parser = ArgumentParsers.newArgumentParser("Bitsquare")
|
||||
.defaultHelp(true)
|
||||
.description("Bitsquare - The decentralized bitcoin exchange.");
|
||||
.description("Bitsquare - The decentralized bitcoin exchange");
|
||||
parser.addArgument("-d", "--" + PEER_ID_FLAG)
|
||||
.help("Seed peer ID.");
|
||||
.setDefault(PEER_ID_DEFAULT)
|
||||
.help("Seed peer ID");
|
||||
parser.addArgument("-p", "--" + PORT_FLAG)
|
||||
.setDefault(PORT_DEFAULT)
|
||||
.help("IP port to listen on.");
|
||||
parser.addArgument("-i", "--" + INFHINT_FLAG)
|
||||
.help("Network interface to listen on.");
|
||||
.setDefault(Node.DEFAULT_PORT)
|
||||
.help("Port to listen on");
|
||||
parser.addArgument("-i", "--" + INTERFACE_HINT_FLAG)
|
||||
.help("Network interface to listen on");
|
||||
parser.addArgument("-n", "--" + NAME_FLAG)
|
||||
.help("Append name to application name.");
|
||||
.help("Name to append name to default application name");
|
||||
}
|
||||
|
||||
public Namespace parseArgs(String... args) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import io.bitsquare.app.ArgumentParser;
|
|||
import io.bitsquare.msg.actor.DHTManager;
|
||||
import io.bitsquare.msg.actor.command.InitializePeer;
|
||||
import io.bitsquare.msg.actor.event.PeerInitialized;
|
||||
import io.bitsquare.network.BootstrapNode;
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -52,19 +52,17 @@ public class SeedNode {
|
|||
ArgumentParser parser = new ArgumentParser();
|
||||
Namespace namespace = parser.parseArgs(args);
|
||||
|
||||
if (namespace.getString(ArgumentParser.INFHINT_FLAG) != null) {
|
||||
interfaceHint = namespace.getString(ArgumentParser.INFHINT_FLAG);
|
||||
}
|
||||
if (namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG) != null)
|
||||
interfaceHint = namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG);
|
||||
|
||||
int serverPort = Integer.valueOf(namespace.getString(ArgumentParser.PORT_FLAG));
|
||||
|
||||
String seedID = BootstrapNode.LOCAL_HOST.getId();
|
||||
String seedID = BootstrapNodes.LOCALHOST.getId();
|
||||
if (namespace.getString(ArgumentParser.PEER_ID_FLAG) != null) {
|
||||
seedID = namespace.getString(ArgumentParser.PEER_ID_FLAG);
|
||||
}
|
||||
|
||||
final Set<PeerAddress> peerAddresses = new HashSet<>();
|
||||
for (Node node : BootstrapNode.values()) {
|
||||
for (Node node : BootstrapNodes.all()) {
|
||||
if (!node.getId().equals(seedID)) {
|
||||
try {
|
||||
peerAddresses.add(new PeerAddress(Number160.createHash(node.getId()), node.getIp(),
|
||||
|
@ -81,14 +79,15 @@ public class SeedNode {
|
|||
inbox.send(seedNode, new InitializePeer(Number160.createHash(seedID), serverPort, interfaceHint,
|
||||
peerAddresses));
|
||||
|
||||
final String _seedID = seedID;
|
||||
Thread seedNodeThread = new Thread(() -> {
|
||||
Boolean quit = false;
|
||||
while (!quit) {
|
||||
try {
|
||||
Object m = inbox.receive(FiniteDuration.create(5L, "seconds"));
|
||||
if (m instanceof PeerInitialized) {
|
||||
log.debug("Seed Peer Initialized on port " + ((PeerInitialized) m).getPort
|
||||
());
|
||||
log.debug("Seed Peer with ID " + _seedID +
|
||||
" initialized on port " + ((PeerInitialized) m).getPort());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!(e instanceof TimeoutException)) {
|
||||
|
|
|
@ -30,15 +30,17 @@ import java.util.Properties;
|
|||
|
||||
public class BitcoinModule extends AbstractBitsquareModule {
|
||||
|
||||
private final BitcoinNetwork defaultNetwork;
|
||||
private static final BitcoinNetwork DEFAULT_NETWORK = BitcoinNetwork.REGTEST;
|
||||
|
||||
private final BitcoinNetwork network;
|
||||
|
||||
public BitcoinModule(Properties properties) {
|
||||
this(properties, BitcoinNetwork.REGTEST);
|
||||
this(properties, DEFAULT_NETWORK);
|
||||
}
|
||||
|
||||
public BitcoinModule(Properties properties, BitcoinNetwork defaultNetwork) {
|
||||
public BitcoinModule(Properties properties, BitcoinNetwork network) {
|
||||
super(properties);
|
||||
this.defaultNetwork = defaultNetwork;
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +57,7 @@ public class BitcoinModule extends AbstractBitsquareModule {
|
|||
}
|
||||
|
||||
private NetworkParameters network() {
|
||||
String networkName = properties.getProperty("networkType", defaultNetwork.name());
|
||||
String networkName = properties.getProperty("networkType", network.name());
|
||||
|
||||
switch (BitcoinNetwork.valueOf(networkName.toUpperCase())) {
|
||||
case MAINNET:
|
||||
|
|
|
@ -18,5 +18,5 @@
|
|||
package io.bitsquare.btc;
|
||||
|
||||
public enum BitcoinNetwork {
|
||||
MAINNET, TESTNET, REGTEST;
|
||||
MAINNET, TESTNET, REGTEST
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ import javax.inject.Named;
|
|||
import javafx.application.Platform;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -186,7 +188,7 @@ public class WalletFacade {
|
|||
|
||||
walletAppKit.addListener(new Service.Listener() {
|
||||
@Override
|
||||
public void failed(Service.State from, Throwable failure) {
|
||||
public void failed(@NotNull Service.State from, @NotNull Throwable failure) {
|
||||
walletAppKit = null;
|
||||
// TODO show error popup
|
||||
//crashAlert(failure);
|
||||
|
|
|
@ -38,8 +38,8 @@ public class SystemTray {
|
|||
private static final String ICON_HI_RES = "/images/system_tray_icon@2x.png";
|
||||
private static final String ICON_LO_RES = "/images/system_tray_icon.png";
|
||||
|
||||
public static final String SHOW_WINDOW_LABEL = "Show exchange window";
|
||||
public static final String HIDE_WINDOW_LABEL = "Hide exchange window";
|
||||
private static final String SHOW_WINDOW_LABEL = "Show exchange window";
|
||||
private static final String HIDE_WINDOW_LABEL = "Hide exchange window";
|
||||
|
||||
private final Stage stage;
|
||||
private final Runnable onExit;
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.bitsquare.gui.UIModel;
|
|||
import io.bitsquare.gui.util.Profiler;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
||||
import io.bitsquare.network.BootstrapState;
|
||||
import io.bitsquare.persistence.Persistence;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
|
@ -44,6 +45,8 @@ import javafx.beans.property.ObjectProperty;
|
|||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.MapChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
|
@ -62,11 +65,13 @@ class MainModel extends UIModel {
|
|||
|
||||
private boolean messageFacadeInited;
|
||||
private boolean walletFacadeInited;
|
||||
private boolean facadesInitialised;
|
||||
|
||||
final BooleanProperty backendReady = new SimpleBooleanProperty();
|
||||
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(-1);
|
||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0);
|
||||
private boolean facadesInitialised;
|
||||
final StringProperty bootstrapState = new SimpleStringProperty();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -122,6 +127,11 @@ class MainModel extends UIModel {
|
|||
public void onFailed(Throwable throwable) {
|
||||
log.error(throwable.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBootstrapStateChanged(BootstrapState bootstrapState) {
|
||||
MainModel.this.bootstrapState.set(bootstrapState.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
Profiler.printMsgWithTime("MainModel.initFacades");
|
||||
|
|
|
@ -42,15 +42,17 @@ import org.slf4j.LoggerFactory;
|
|||
class MainPM extends PresentationModel<MainModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainPM.class);
|
||||
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
final BooleanProperty backendReady = new SimpleBooleanProperty();
|
||||
final StringProperty bankAccountsComboBoxPrompt = new SimpleStringProperty();
|
||||
final BooleanProperty bankAccountsComboBoxDisable = new SimpleBooleanProperty();
|
||||
final StringProperty splashScreenInfoText = new SimpleStringProperty();
|
||||
final StringProperty bootstrapState = new SimpleStringProperty();
|
||||
final StringProperty bitcoinSyncState = new SimpleStringProperty("Initializing");
|
||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty();
|
||||
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -61,11 +63,11 @@ class MainPM extends PresentationModel<MainModel> {
|
|||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
@ -75,16 +77,13 @@ class MainPM extends PresentationModel<MainModel> {
|
|||
networkSyncProgress.bind(model.networkSyncProgress);
|
||||
numPendingTrades.bind(model.numPendingTrades);
|
||||
|
||||
model.networkSyncProgress.addListener((ov, oldValue, newValue) -> {
|
||||
if ((double) newValue > 0.0)
|
||||
splashScreenInfoText.set("Synchronise with network " + formatter.formatToPercent((double)
|
||||
newValue));
|
||||
else if ((double) newValue == 1)
|
||||
splashScreenInfoText.set("Synchronise with network completed.");
|
||||
else
|
||||
splashScreenInfoText.set("Synchronise with network...");
|
||||
});
|
||||
splashScreenInfoText.set("Synchronise with network...");
|
||||
model.bootstrapState.addListener((ov, oldValue, newValue) ->
|
||||
bootstrapState.set("Connection to P2P network: " + newValue));
|
||||
|
||||
bootstrapState.set(model.bootstrapState.get());
|
||||
|
||||
model.networkSyncProgress.addListener((ov, oldValue, newValue) -> updateBitcoinSyncState((double) newValue));
|
||||
updateBitcoinSyncState(model.networkSyncProgress.get());
|
||||
|
||||
model.getBankAccounts().addListener((ListChangeListener<BankAccount>) change -> {
|
||||
bankAccountsComboBoxDisable.set(change.getList().isEmpty());
|
||||
|
@ -145,4 +144,19 @@ class MainPM extends PresentationModel<MainModel> {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateBitcoinSyncState(double value) {
|
||||
if (value > 0.0)
|
||||
bitcoinSyncState.set("Synchronizing with bitcoin network: " +
|
||||
formatter.formatToPercent(value));
|
||||
else if (value == 1)
|
||||
bitcoinSyncState.set("Synchronizing with bitcoin network completed.");
|
||||
else
|
||||
bitcoinSyncState.set("Synchronizing with bitcoin network...");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import javafx.scene.effect.*;
|
|||
import javafx.scene.image.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.*;
|
||||
import javafx.scene.text.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -167,7 +168,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||
((StackPane) root).getChildren().addAll(baseApplicationContainer, splashScreen);
|
||||
baseApplicationContainer.setCenter(getApplicationContainer());
|
||||
|
||||
Platform.runLater(() -> onSplashScreenAdded());
|
||||
Platform.runLater(this::onSplashScreenAdded);
|
||||
}
|
||||
|
||||
private void onSplashScreenAdded() {
|
||||
|
@ -285,16 +286,35 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||
ImageView logo = new ImageView();
|
||||
logo.setId("image-splash-logo");
|
||||
|
||||
Label loadingLabel = new Label();
|
||||
loadingLabel.setAlignment(Pos.CENTER);
|
||||
loadingLabel.setPadding(new Insets(60, 0, 0, 0));
|
||||
loadingLabel.textProperty().bind(presentationModel.splashScreenInfoText);
|
||||
Label bitcoinSyncStateLabel = new Label();
|
||||
bitcoinSyncStateLabel.textProperty().bind(presentationModel.bitcoinSyncState);
|
||||
|
||||
ProgressBar progressBar = new ProgressBar();
|
||||
progressBar.setPrefWidth(240);
|
||||
progressBar.progressProperty().bind(presentationModel.networkSyncProgress);
|
||||
ProgressBar btcProgressIndicator = new ProgressBar(-1);
|
||||
btcProgressIndicator.setPrefWidth(120);
|
||||
btcProgressIndicator.progressProperty().bind(presentationModel.networkSyncProgress);
|
||||
|
||||
vBox.getChildren().addAll(logo, loadingLabel, progressBar);
|
||||
HBox btcBox = new HBox();
|
||||
btcBox.setSpacing(10);
|
||||
btcBox.setAlignment(Pos.CENTER);
|
||||
btcBox.setPadding(new Insets(60, 0, 0, 0));
|
||||
btcBox.getChildren().addAll(bitcoinSyncStateLabel, btcProgressIndicator);
|
||||
|
||||
Label bootstrapStateLabel = new Label();
|
||||
bootstrapStateLabel.setWrapText(true);
|
||||
bootstrapStateLabel.setMaxWidth(500);
|
||||
bootstrapStateLabel.setTextAlignment(TextAlignment.CENTER);
|
||||
bootstrapStateLabel.textProperty().bind(presentationModel.bootstrapState);
|
||||
|
||||
ProgressIndicator p2pProgressIndicator = new ProgressIndicator(-1);
|
||||
p2pProgressIndicator.setMaxSize(24, 24);
|
||||
|
||||
HBox p2pBox = new HBox();
|
||||
p2pBox.setSpacing(10);
|
||||
p2pBox.setAlignment(Pos.CENTER);
|
||||
p2pBox.setPadding(new Insets(10, 0, 0, 0));
|
||||
p2pBox.getChildren().addAll(bootstrapStateLabel, p2pProgressIndicator);
|
||||
|
||||
vBox.getChildren().addAll(logo, btcBox, p2pBox);
|
||||
|
||||
return vBox;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ArbitratorBrowserViewCB extends CachedViewCB implements ArbitratorL
|
|||
|
||||
private final Settings settings;
|
||||
private final Persistence persistence;
|
||||
private MessageFacade messageFacade;
|
||||
private final MessageFacade messageFacade;
|
||||
|
||||
private final List<Arbitrator> allArbitrators = new ArrayList<>();
|
||||
private Arbitrator currentArbitrator;
|
||||
|
|
|
@ -38,13 +38,13 @@ public class ArbitratorProfileViewCB extends CachedViewCB {
|
|||
private final Settings settings;
|
||||
|
||||
private final Persistence persistence;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
|
||||
@FXML Label nameLabel;
|
||||
@FXML TextField nameTextField, languagesTextField, reputationTextField,
|
||||
feeTextField, methodsTextField,
|
||||
idVerificationsTextField, webPageTextField;
|
||||
feeTextField, methodsTextField, passiveServiceFeeTextField,
|
||||
idVerificationsTextField, webPageTextField, maxTradeVolumeTextField;
|
||||
@FXML TextArea descriptionTextArea;
|
||||
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class ArbitratorRegistrationViewCB extends CachedViewCB {
|
|||
private final WalletFacade walletFacade;
|
||||
private final MessageFacade messageFacade;
|
||||
private final User user;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private Arbitrator arbitrator = new Arbitrator();
|
||||
private boolean isEditMode;
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
|
|||
@FXML ComboBox<BankAccount> selectionComboBox;
|
||||
@FXML ComboBox<BankAccountType> typesComboBox;
|
||||
@FXML ComboBox<Currency> currencyComboBox;
|
||||
private OverlayManager overlayManager;
|
||||
private final OverlayManager overlayManager;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -59,7 +59,7 @@ class IrcAccountModel extends UIModel {
|
|||
|
||||
private final User user;
|
||||
private final Settings settings;
|
||||
private MessageFacade messageFacade;
|
||||
private final MessageFacade messageFacade;
|
||||
private final Persistence persistence;
|
||||
|
||||
final StringProperty nickName = new SimpleStringProperty();
|
||||
|
|
|
@ -123,17 +123,15 @@ public class IrcAccountViewCB extends CachedViewCB<IrcAccountPm> implements Cont
|
|||
setupListeners();
|
||||
setupBindings();
|
||||
|
||||
Platform.runLater(() -> {
|
||||
Popups.openInfoPopup("Demo setup for simulating the banking transfer",
|
||||
"For demo purposes we use a special setup so that users can simulate the banking transfer when " +
|
||||
"meeting in an IRC chat room.\n" +
|
||||
"You need to define your IRC nickname and later in the trade process you can find your " +
|
||||
"trading partner with his IRC nickname in the chat room and simulate the bank transfer " +
|
||||
"activities, which are:\n\n" +
|
||||
"1. Bitcoin buyer indicates that he has started the bank transfer.\n\n" +
|
||||
"2. Bitcoin seller confirms that he has received the national currency from the " +
|
||||
"bank transfer.");
|
||||
});
|
||||
Platform.runLater(() -> Popups.openInfoPopup("Demo setup for simulating the banking transfer",
|
||||
"For demo purposes we use a special setup so that users can simulate the banking transfer when " +
|
||||
"meeting in an IRC chat room.\n" +
|
||||
"You need to define your IRC nickname and later in the trade process you can find your " +
|
||||
"trading partner with his IRC nickname in the chat room and simulate the bank transfer " +
|
||||
"activities, which are:\n\n" +
|
||||
"1. Bitcoin buyer indicates that he has started the bank transfer.\n\n" +
|
||||
"2. Bitcoin seller confirms that he has received the national currency from the " +
|
||||
"bank transfer."));
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
|
|
|
@ -47,7 +47,7 @@ class RegistrationPM extends PresentationModel<RegistrationModel> {
|
|||
|
||||
// That is needed for the addressTextField
|
||||
final ObjectProperty<Address> address = new SimpleObjectProperty<>();
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -32,7 +32,7 @@ class SeedWordsPM extends PresentationModel<SeedWordsModel> {
|
|||
private static final Logger log = LoggerFactory.getLogger(SeedWordsPM.class);
|
||||
|
||||
final StringProperty seedWords = new SimpleStringProperty();
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -52,8 +52,8 @@ public class AccountSettingsViewCB extends CachedViewCB {
|
|||
private final Navigation navigation;
|
||||
private Navigation.Listener listener;
|
||||
|
||||
@FXML VBox leftVBox;
|
||||
@FXML AnchorPane content;
|
||||
@FXML private VBox leftVBox;
|
||||
@FXML private AnchorPane content;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -46,7 +46,7 @@ public class TransactionsViewCB extends CachedViewCB {
|
|||
private static final Logger log = LoggerFactory.getLogger(TransactionsViewCB.class);
|
||||
|
||||
private final WalletFacade walletFacade;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private ObservableList<TransactionsListItem> transactionsListItems;
|
||||
|
||||
@FXML TableView<TransactionsListItem> table;
|
||||
|
|
|
@ -43,7 +43,7 @@ public class WithdrawalListItem {
|
|||
private final AddressEntry addressEntry;
|
||||
|
||||
private final WalletFacade walletFacade;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private final AddressConfidenceListener confidenceListener;
|
||||
|
||||
private final ConfidenceProgressIndicator progressIndicator;
|
||||
|
|
|
@ -64,7 +64,7 @@ public class WithdrawalViewCB extends CachedViewCB {
|
|||
|
||||
|
||||
private final WalletFacade walletFacade;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private final ObservableList<WithdrawalListItem> addressList = FXCollections.observableArrayList();
|
||||
|
||||
@FXML TableView<WithdrawalListItem> table;
|
||||
|
|
|
@ -37,7 +37,7 @@ class ClosedTradesModel extends UIModel {
|
|||
private static final Logger log = LoggerFactory.getLogger(ClosedTradesModel.class);
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private User user;
|
||||
private final User user;
|
||||
|
||||
private final ObservableList<ClosedTradesListItem> list = FXCollections.observableArrayList();
|
||||
private MapChangeListener<String, Trade> mapChangeListener;
|
||||
|
|
|
@ -38,7 +38,7 @@ class OffersModel extends UIModel {
|
|||
private static final Logger log = LoggerFactory.getLogger(OffersModel.class);
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private User user;
|
||||
private final User user;
|
||||
|
||||
private final ObservableList<OfferListItem> list = FXCollections.observableArrayList();
|
||||
private MapChangeListener<String, Offer> offerMapChangeListener;
|
||||
|
|
|
@ -226,10 +226,7 @@ class PendingTradesModel extends UIModel {
|
|||
String fromAddress = addressEntry.getAddressString();
|
||||
try {
|
||||
walletFacade.sendFunds(fromAddress, toAddress, getAmountToWithdraw(), callback);
|
||||
} catch (AddressFormatException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
} catch (InsufficientMoneyException e) {
|
||||
} catch (AddressFormatException | InsufficientMoneyException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
|
|||
|
||||
private final BSFormatter formatter;
|
||||
private InvalidationListener stateChangeListener;
|
||||
private BtcAddressValidator btcAddressValidator;
|
||||
private final BtcAddressValidator btcAddressValidator;
|
||||
|
||||
final StringProperty txId = new SimpleStringProperty();
|
||||
final ObjectProperty<State> state = new SimpleObjectProperty<>();
|
||||
|
|
|
@ -61,7 +61,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
|
|||
private ChangeListener<PendingTradesPM.State> offererStateChangeListener;
|
||||
private ChangeListener<PendingTradesPM.State> takerStateChangeListener;
|
||||
private ChangeListener<Throwable> faultChangeListener;
|
||||
private Navigation navigation;
|
||||
private final Navigation navigation;
|
||||
|
||||
@FXML ScrollPane scrollPane;
|
||||
@FXML GridPane gridPane;
|
||||
|
|
|
@ -70,8 +70,8 @@ class CreateOfferModel extends UIModel {
|
|||
private final WalletFacade walletFacade;
|
||||
private final Settings settings;
|
||||
private final User user;
|
||||
private Persistence persistence;
|
||||
private BSFormatter formatter;
|
||||
private final Persistence persistence;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
private final String offerId;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class CreateOfferPM extends PresentationModel<CreateOfferModel> {
|
|||
private static final Logger log = LoggerFactory.getLogger(CreateOfferPM.class);
|
||||
|
||||
private final BtcValidator btcValidator;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private final FiatValidator fiatValidator;
|
||||
|
||||
final StringProperty amount = new SimpleStringProperty();
|
||||
|
|
|
@ -172,7 +172,7 @@ public class OfferBook {
|
|||
private void startPolling() {
|
||||
addListeners();
|
||||
setBankAccount(user.getCurrentBankAccount());
|
||||
pollingTimer = Utilities.setInterval(1000, (animationTimer) -> {
|
||||
pollingTimer = Utilities.setInterval(3000, (animationTimer) -> {
|
||||
offerRepository.requestInvalidationTimeStampFromDHT(fiatCode);
|
||||
return null;
|
||||
});
|
||||
|
|
|
@ -57,7 +57,7 @@ class OfferBookModel extends UIModel {
|
|||
private final User user;
|
||||
private final OfferBook offerBook;
|
||||
private final Settings settings;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private final TradeManager tradeManager;
|
||||
|
||||
private final FilteredList<OfferBookListItem> filteredItems;
|
||||
|
|
|
@ -42,7 +42,7 @@ class OfferBookPM extends PresentationModel<OfferBookModel> {
|
|||
private static final Logger log = LoggerFactory.getLogger(OfferBookPM.class);
|
||||
|
||||
private final OptionalBtcValidator optionalBtcValidator;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
private final OptionalFiatValidator optionalFiatValidator;
|
||||
|
||||
final StringProperty amount = new SimpleStringProperty();
|
||||
|
|
|
@ -57,7 +57,7 @@ class TakeOfferModel extends UIModel {
|
|||
private final TradeManager tradeManager;
|
||||
private final WalletFacade walletFacade;
|
||||
private final Settings settings;
|
||||
private Persistence persistence;
|
||||
private final Persistence persistence;
|
||||
|
||||
private Offer offer;
|
||||
private AddressEntry addressEntry;
|
||||
|
|
|
@ -65,7 +65,7 @@ class TakeOfferPM extends PresentationModel<TakeOfferModel> {
|
|||
final ObjectProperty<Address> address = new SimpleObjectProperty<>();
|
||||
|
||||
private final BtcValidator btcValidator;
|
||||
private BSFormatter formatter;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
final StringProperty amount = new SimpleStringProperty();
|
||||
final StringProperty volume = new SimpleStringProperty();
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public final class BtcAddressValidator extends InputValidator {
|
||||
private static final Logger log = LoggerFactory.getLogger(BtcAddressValidator.class);
|
||||
private NetworkParameters networkParameters;
|
||||
private final NetworkParameters networkParameters;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -36,7 +36,7 @@ public abstract class ActorService extends Service<String> {
|
|||
|
||||
private final ActorSystem system;
|
||||
private final Inbox inbox;
|
||||
private ActorSelection actor;
|
||||
private final ActorSelection actor;
|
||||
|
||||
private MessageHandler handler;
|
||||
|
||||
|
@ -71,12 +71,7 @@ public abstract class ActorService extends Service<String> {
|
|||
if (result != null) {
|
||||
System.out.println(result.toString());
|
||||
if (handler != null) {
|
||||
Application.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handler.handle(result);
|
||||
}
|
||||
});
|
||||
Application.invokeLater(() -> handler.handle(result));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.network.BootstrapState;
|
||||
import io.bitsquare.network.Node;
|
||||
import io.bitsquare.persistence.Persistence;
|
||||
|
||||
|
@ -32,13 +33,11 @@ import java.net.UnknownHostException;
|
|||
|
||||
import java.security.KeyPair;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
|
@ -66,7 +65,6 @@ import org.slf4j.LoggerFactory;
|
|||
/**
|
||||
* Creates a DHT peer and bootstrap to the network via a seed node
|
||||
*/
|
||||
@Immutable
|
||||
public class BootstrappedPeerFactory {
|
||||
private static final Logger log = LoggerFactory.getLogger(BootstrappedPeerFactory.class);
|
||||
|
||||
|
@ -76,7 +74,9 @@ public class BootstrappedPeerFactory {
|
|||
private final Persistence persistence;
|
||||
|
||||
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
|
||||
public final StringProperty connectionState = new SimpleStringProperty();
|
||||
public final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
|
||||
private Peer peer;
|
||||
private PeerDHT peerDHT;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -109,8 +109,9 @@ public class BootstrappedPeerFactory {
|
|||
|
||||
public ListenableFuture<PeerDHT> start(int port) {
|
||||
try {
|
||||
Peer peer = new PeerBuilder(keyPair).ports(port).behindFirewall().start();
|
||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(storage)).start();
|
||||
setState(BootstrapState.PEER_CREATION, "We create a P2P node.");
|
||||
peer = new PeerBuilder(keyPair).ports(port).start();
|
||||
peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(storage)).start();
|
||||
|
||||
peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() {
|
||||
@Override
|
||||
|
@ -147,29 +148,24 @@ public class BootstrappedPeerFactory {
|
|||
lastSuccessfulBootstrap = "default";
|
||||
|
||||
log.debug("lastSuccessfulBootstrap = " + lastSuccessfulBootstrap);
|
||||
FutureDiscover futureDiscover;
|
||||
|
||||
// just temporary while port forwarding is not working
|
||||
lastSuccessfulBootstrap = "default";
|
||||
|
||||
switch (lastSuccessfulBootstrap) {
|
||||
case "relay":
|
||||
futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peerDHT.peer()).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
bootstrapWithRelay(peerDHT, peerNAT, futureDiscover, futureNAT);
|
||||
bootstrapWithRelay();
|
||||
break;
|
||||
case "portForwarding":
|
||||
futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||
tryPortForwarding(peerDHT, futureDiscover);
|
||||
tryPortForwarding();
|
||||
break;
|
||||
case "default":
|
||||
default:
|
||||
discover(peerDHT);
|
||||
discover();
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
setState("Cannot create peer with port: " + port + ". Exeption: " + e, false);
|
||||
setState(BootstrapState.PEER_CREATION, "Cannot create peer with port: " + port + ". Exeption: " + e, false);
|
||||
settableFuture.setException(e);
|
||||
}
|
||||
|
||||
|
@ -177,28 +173,28 @@ public class BootstrappedPeerFactory {
|
|||
}
|
||||
|
||||
// 1. Attempt: Try to discover our outside visible address
|
||||
private void discover(PeerDHT peerDHT) {
|
||||
FutureDiscover futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||
private void discover() {
|
||||
setState(BootstrapState.DIRECT_INIT, "We are starting to bootstrap to a seed node.");
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
||||
futureDiscover.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
setState("We are visible to other peers: My address visible to " +
|
||||
"the outside is " + futureDiscover.peerAddress());
|
||||
setState(BootstrapState.DIRECT_SUCCESS, "We are directly connected and visible to other peers.");
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||
settableFuture.set(peerDHT);
|
||||
}
|
||||
else {
|
||||
setState("We are probably behind a NAT and not reachable to other peers. " +
|
||||
"We try port forwarding as next step.");
|
||||
setState(BootstrapState.DIRECT_NOT_SUCCEEDED, "We are probably behind a NAT and not reachable to " +
|
||||
"other peers. We try to setup automatic port forwarding.");
|
||||
|
||||
tryPortForwarding(peerDHT, futureDiscover);
|
||||
tryPortForwarding();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable t) throws Exception {
|
||||
setState("Exception at discover: " + t.getMessage(), false);
|
||||
setState(BootstrapState.DIRECT_FAILED, "Exception at discover: " + t.getMessage(), false);
|
||||
peerDHT.shutdown();
|
||||
settableFuture.setException(t);
|
||||
}
|
||||
|
@ -206,26 +202,30 @@ public class BootstrappedPeerFactory {
|
|||
}
|
||||
|
||||
// 2. Attempt: Try to set up port forwarding with UPNP and NAT-PMP
|
||||
private void tryPortForwarding(PeerDHT peerDHT, FutureDiscover futureDiscover) {
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peerDHT.peer()).start();
|
||||
private void tryPortForwarding() {
|
||||
setState(BootstrapState.NAT_INIT, "We are trying with automatic port forwarding.");
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
futureNAT.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
setState("Automatic port forwarding is setup. Address = " + futureNAT.peerAddress());
|
||||
setState(BootstrapState.NAT_SETUP_DONE, "Automatic port forwarding is setup. " +
|
||||
"We need to do a discover process again.");
|
||||
// we need a second discover process
|
||||
discoverAfterPortForwarding(peerDHT);
|
||||
discoverAfterPortForwarding();
|
||||
}
|
||||
else {
|
||||
setState("Port forwarding has failed. We try to use a relay as next step.");
|
||||
bootstrapWithRelay(peerDHT, peerNAT, futureDiscover, futureNAT);
|
||||
setState(BootstrapState.NAT_NOT_SUCCEEDED, "Port forwarding has failed. " +
|
||||
"We try to use a relay as next step.");
|
||||
bootstrapWithRelay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable t) throws Exception {
|
||||
setState("Exception at port forwarding: " + t.getMessage(), false);
|
||||
setState(BootstrapState.NAT_FAILED, "Exception at port forwarding: " + t.getMessage(), false);
|
||||
peerDHT.shutdown();
|
||||
settableFuture.setException(t);
|
||||
}
|
||||
|
@ -233,20 +233,19 @@ public class BootstrappedPeerFactory {
|
|||
}
|
||||
|
||||
// Try to determine our outside visible address after port forwarding is setup
|
||||
private void discoverAfterPortForwarding(PeerDHT peerDHT) {
|
||||
FutureDiscover futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||
private void discoverAfterPortForwarding() {
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
||||
futureDiscover.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
setState("Discover with automatic port forwarding was successful. " +
|
||||
"My address visible to the outside is = " + futureDiscover.peerAddress());
|
||||
setState(BootstrapState.NAT_SUCCESS, "Discover with automatic port forwarding was successful.");
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "portForwarding");
|
||||
settableFuture.set(peerDHT);
|
||||
}
|
||||
else {
|
||||
setState("Discover with automatic port forwarding has failed " + futureDiscover
|
||||
.failedReason(), false);
|
||||
setState(BootstrapState.NAT_FAILED, "Discover with automatic port forwarding has failed " +
|
||||
futureDiscover.failedReason(), false);
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||
peerDHT.shutdown();
|
||||
settableFuture.setException(new Exception("Discover with automatic port forwarding failed " +
|
||||
|
@ -256,7 +255,7 @@ public class BootstrappedPeerFactory {
|
|||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable t) throws Exception {
|
||||
setState("Exception at discover: " + t, false);
|
||||
setState(BootstrapState.NAT_FAILED, "Exception at discover: " + t, false);
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||
peerDHT.shutdown();
|
||||
settableFuture.setException(t);
|
||||
|
@ -265,20 +264,23 @@ public class BootstrappedPeerFactory {
|
|||
}
|
||||
|
||||
// 3. Attempt: We try to use another peer as relay
|
||||
private void bootstrapWithRelay(PeerDHT peerDHT, PeerNAT peerNAT, FutureDiscover futureDiscover,
|
||||
FutureNAT futureNAT) {
|
||||
private void bootstrapWithRelay() {
|
||||
setState(BootstrapState.RELAY_INIT, "We try to use another peer as relay.");
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(futureDiscover, futureNAT);
|
||||
futureRelayNAT.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
setState("Bootstrap using relay was successful. " +
|
||||
"My address visible to the outside is = " + peerDHT.peerAddress());
|
||||
setState(BootstrapState.RELAY_SUCCESS, "Bootstrap using relay was successful.");
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "relay");
|
||||
settableFuture.set(peerDHT);
|
||||
}
|
||||
else {
|
||||
setState("Bootstrap using relay has failed " + futureRelayNAT.failedReason(), false);
|
||||
setState(BootstrapState.RELAY_FAILED, "Bootstrap using relay has failed " + futureRelayNAT
|
||||
.failedReason(), false);
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||
futureRelayNAT.shutdown();
|
||||
peerDHT.shutdown();
|
||||
|
@ -289,14 +291,13 @@ public class BootstrappedPeerFactory {
|
|||
|
||||
@Override
|
||||
public void exceptionCaught(Throwable t) throws Exception {
|
||||
setState("Exception at bootstrapWithRelay: " + t, false);
|
||||
setState(BootstrapState.RELAY_FAILED, "Exception at bootstrapWithRelay: " + t, false);
|
||||
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||
futureRelayNAT.shutdown();
|
||||
peerDHT.shutdown();
|
||||
settableFuture.setException(t);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private PeerAddress getBootstrapAddress() {
|
||||
|
@ -311,15 +312,17 @@ public class BootstrappedPeerFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private void setState(String state) {
|
||||
setState(state, true);
|
||||
private void setState(BootstrapState bootstrapState, String message) {
|
||||
setState(bootstrapState, message, true);
|
||||
}
|
||||
|
||||
private void setState(String state, boolean isSuccess) {
|
||||
private void setState(BootstrapState bootstrapState, String message, boolean isSuccess) {
|
||||
if (isSuccess)
|
||||
log.info(state);
|
||||
log.info(message);
|
||||
else
|
||||
log.error(state);
|
||||
Platform.runLater(() -> connectionState.set(state));
|
||||
log.error(message);
|
||||
|
||||
bootstrapState.setMessage(message);
|
||||
Platform.runLater(() -> this.bootstrapState.set(bootstrapState));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.AbstractBitsquareModule;
|
||||
import io.bitsquare.network.BootstrapNode;
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
|
@ -44,7 +44,7 @@ public class DefaultMessageModule extends AbstractBitsquareModule implements Mes
|
|||
|
||||
bind(Node.class)
|
||||
.annotatedWith(Names.named("bootstrapNode"))
|
||||
.toInstance(BootstrapNode.LOCAL_HOST);
|
||||
.toInstance(BootstrapNodes.LOCALHOST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
||||
import io.bitsquare.network.tomp2p.TomP2PPeer;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
|
@ -38,6 +39,8 @@ import javax.annotation.Nullable;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
||||
import net.tomp2p.connection.DSASignatureFactory;
|
||||
import net.tomp2p.connection.PeerConnection;
|
||||
import net.tomp2p.dht.FutureGet;
|
||||
|
@ -117,14 +120,29 @@ public class P2PNode {
|
|||
bootstrappedPeerFactory.setKeyPair(keyPair);
|
||||
}
|
||||
|
||||
public void start(int port, FutureCallback<PeerDHT> callback) {
|
||||
public void start(int port, BootstrapListener bootstrapListener) {
|
||||
useDiscStorage(useDiskStorage);
|
||||
|
||||
bootstrappedPeerFactory.setStorage(storage);
|
||||
setupTimerForIPCheck();
|
||||
|
||||
ListenableFuture<PeerDHT> bootstrapComplete = bootstrap(port);
|
||||
Futures.addCallback(bootstrapComplete, callback);
|
||||
Futures.addCallback(bootstrapComplete, new FutureCallback<PeerDHT>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable PeerDHT result) {
|
||||
log.debug("p2pNode.start success result = " + result);
|
||||
Platform.runLater(bootstrapListener::onCompleted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
log.error(t.toString());
|
||||
Platform.runLater(() -> bootstrapListener.onFailed(t));
|
||||
}
|
||||
});
|
||||
|
||||
bootstrappedPeerFactory.bootstrapState.addListener((ov, oldValue, newValue) ->
|
||||
bootstrapListener.onBootstrapStateChanged(newValue));
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,7 +205,7 @@ public class P2PNode {
|
|||
futureDirect.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (futureDirect.isSuccess()) {
|
||||
if (isSuccess(futureDirect)) {
|
||||
log.debug("sendMessage completed");
|
||||
}
|
||||
else {
|
||||
|
@ -297,7 +315,7 @@ public class P2PNode {
|
|||
futurePut.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
if (isSuccess(futurePut)) {
|
||||
storedPeerAddress = peerDHT.peerAddress();
|
||||
log.debug("storedPeerAddress = " + storedPeerAddress);
|
||||
}
|
||||
|
@ -382,4 +400,10 @@ public class P2PNode {
|
|||
storage = new StorageMemory();
|
||||
}
|
||||
}
|
||||
|
||||
// Isolate the success handling as there is bug in port forwarding mode
|
||||
private boolean isSuccess(BaseFuture baseFuture) {
|
||||
// return baseFuture.isSuccess();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ import io.bitsquare.network.Peer;
|
|||
import io.bitsquare.network.tomp2p.TomP2PPeer;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
@ -37,8 +35,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
@ -46,7 +42,6 @@ import javafx.application.Platform;
|
|||
import net.tomp2p.dht.FutureGet;
|
||||
import net.tomp2p.dht.FuturePut;
|
||||
import net.tomp2p.dht.FutureRemove;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.futures.BaseFuture;
|
||||
import net.tomp2p.futures.BaseFutureAdapter;
|
||||
import net.tomp2p.futures.BaseFutureListener;
|
||||
|
@ -55,11 +50,10 @@ import net.tomp2p.peers.Number160;
|
|||
import net.tomp2p.storage.Data;
|
||||
import net.tomp2p.utils.Utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* That facade delivers direct messaging and DHT functionality from the TomP2P library
|
||||
* It is the translating domain specific functionality to the messaging layer.
|
||||
|
@ -98,19 +92,7 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
p2pNode.setMessageBroker(this);
|
||||
p2pNode.setKeyPair(user.getMessageKeyPair());
|
||||
|
||||
p2pNode.start(port, new FutureCallback<PeerDHT>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable PeerDHT result) {
|
||||
log.debug("p2pNode.start success result = " + result);
|
||||
Platform.runLater(bootstrapListener::onCompleted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
log.error(t.toString());
|
||||
Platform.runLater(() -> bootstrapListener.onFailed(t));
|
||||
}
|
||||
});
|
||||
p2pNode.start(port, bootstrapListener);
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
|
@ -131,7 +113,7 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception {
|
||||
if (baseFuture.isSuccess() && futureGet.data() != null) {
|
||||
if (isSuccess(baseFuture) && futureGet.data() != null) {
|
||||
final Peer peer = (Peer) futureGet.data().object();
|
||||
Platform.runLater(() -> listener.onResult(peer));
|
||||
}
|
||||
|
@ -142,7 +124,6 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -150,13 +131,13 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
public void sendMessage(Peer peer, Message message,
|
||||
OutgoingMessageListener listener) {
|
||||
if (!(peer instanceof TomP2PPeer)) {
|
||||
throw new IllegalArgumentException("peer must be of type TomP2PPeer") ;
|
||||
throw new IllegalArgumentException("peer must be of type TomP2PPeer");
|
||||
}
|
||||
FutureDirect futureDirect = p2pNode.sendData(((TomP2PPeer)peer).getPeerAddress(), message);
|
||||
FutureDirect futureDirect = p2pNode.sendData(((TomP2PPeer) peer).getPeerAddress(), message);
|
||||
futureDirect.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (futureDirect.isSuccess()) {
|
||||
if (isSuccess(futureDirect)) {
|
||||
Platform.runLater(listener::onResult);
|
||||
}
|
||||
else {
|
||||
|
@ -198,7 +179,7 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
}
|
||||
}));
|
||||
|
||||
if (addFuture.isSuccess()) {
|
||||
if (isSuccess(addFuture)) {
|
||||
log.trace("Add arbitrator to DHT was successful. Stored data: [key: " + locationKey + ", " +
|
||||
"values: " + arbitratorData + "]");
|
||||
}
|
||||
|
@ -233,7 +214,7 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
}
|
||||
}
|
||||
}));
|
||||
if (removeFuture.isSuccess()) {
|
||||
if (isSuccess(removeFuture)) {
|
||||
log.trace("Remove arbitrator from DHT was successful. Stored data: [key: " + locationKey + ", " +
|
||||
"values: " + arbitratorData + "]");
|
||||
}
|
||||
|
@ -267,7 +248,7 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
|
||||
listener.onArbitratorsReceived(arbitrators);
|
||||
}));
|
||||
if (baseFuture.isSuccess()) {
|
||||
if (isSuccess(baseFuture)) {
|
||||
log.trace("Get arbitrators from DHT was successful. Stored data: [key: " + locationKey + ", " +
|
||||
"values: " + futureGet.dataMap() + "]");
|
||||
}
|
||||
|
@ -299,6 +280,11 @@ class TomP2PMessageFacade implements MessageFacade {
|
|||
incomingMessageListeners.remove(listener);
|
||||
}
|
||||
|
||||
// Isolate the success handling as there is bug in port forwarding mode
|
||||
private boolean isSuccess(BaseFuture baseFuture) {
|
||||
// return baseFuture.isSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message handler
|
||||
|
|
|
@ -52,14 +52,12 @@ public class DHTManager extends AbstractActor {
|
|||
return Props.create(DHTManager.class);
|
||||
}
|
||||
|
||||
private Bindings bindings;
|
||||
private Peer peer;
|
||||
private PeerDHT peerDHT;
|
||||
private PeerNAT peerNAT;
|
||||
|
||||
public DHTManager() {
|
||||
receive(ReceiveBuilder
|
||||
.match(InitializePeer.class, initializePeer -> doInitializePeer(initializePeer))
|
||||
.match(InitializePeer.class, this::doInitializePeer)
|
||||
.matchAny(o -> log.info("received unknown message")).build()
|
||||
);
|
||||
}
|
||||
|
@ -68,7 +66,7 @@ public class DHTManager extends AbstractActor {
|
|||
log.debug("Received message: {}", initializePeer);
|
||||
|
||||
try {
|
||||
bindings = new Bindings();
|
||||
Bindings bindings = new Bindings();
|
||||
|
||||
// TODO: @Steve: Is that needed that we restrict to IP4?
|
||||
// bindings.addProtocol(StandardProtocolFamily.INET);
|
||||
|
@ -77,8 +75,12 @@ public class DHTManager extends AbstractActor {
|
|||
bindings.addInterface(initializePeer.getInterfaceHint());
|
||||
}
|
||||
|
||||
peer = new PeerBuilder(initializePeer.getPeerId()).ports(initializePeer.getPort()).bindings(bindings)
|
||||
Peer peer = new PeerBuilder(initializePeer.getPeerId()).ports(initializePeer.getPort()).bindings(bindings)
|
||||
.start();
|
||||
peer.objectDataReply((sender, request) -> {
|
||||
log.debug("received request: ", request.toString());
|
||||
return "pong";
|
||||
});
|
||||
|
||||
// For the moment we want not to bootstrap to other seed nodes to keep test scenarios
|
||||
// simple
|
||||
|
@ -110,9 +112,7 @@ public class DHTManager extends AbstractActor {
|
|||
|
||||
sender().tell(new PeerInitialized(peer.peerID(), initializePeer.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, null), self());
|
||||
log.error(t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
|
||||
package io.bitsquare.msg.listeners;
|
||||
|
||||
import io.bitsquare.network.BootstrapState;
|
||||
|
||||
public interface BootstrapListener {
|
||||
public void onCompleted();
|
||||
|
||||
public void onFailed(Throwable throwable);
|
||||
|
||||
public void onBootstrapStateChanged(BootstrapState state);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,32 +17,16 @@
|
|||
|
||||
package io.bitsquare.network;
|
||||
|
||||
public enum BootstrapNode implements Node {
|
||||
LOCAL_HOST("localhost", "127.0.0.1", 5000),
|
||||
DIGITAL_OCEAN1("digitalocean1.bitsquare.io", "188.226.179.109", 5000);
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
private final String id;
|
||||
private final String ip;
|
||||
private final int port;
|
||||
public interface BootstrapNodes {
|
||||
Node LOCALHOST = Node.at("localhost", "127.0.0.1");
|
||||
Node DIGITAL_OCEAN_1 = Node.at("digitalocean1.bitsquare.io", "188.226.179.109");
|
||||
|
||||
BootstrapNode(String id, String ip, int port) {
|
||||
this.id = id;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return port;
|
||||
static List<Node> all() {
|
||||
return Arrays.asList(
|
||||
LOCALHOST, DIGITAL_OCEAN_1
|
||||
);
|
||||
}
|
||||
}
|
51
src/main/java/io/bitsquare/network/BootstrapState.java
Normal file
51
src/main/java/io/bitsquare/network/BootstrapState.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.network;
|
||||
|
||||
/**
|
||||
* NOT_SUCCEEDED means we will try the next step, FAILED is used for fatal failures which will terminate the bootstrap
|
||||
*/
|
||||
public enum BootstrapState {
|
||||
PEER_CREATION,
|
||||
PEER_CREATION_FAILED,
|
||||
DIRECT_INIT,
|
||||
DIRECT_SUCCESS,
|
||||
DIRECT_NOT_SUCCEEDED,
|
||||
DIRECT_FAILED,
|
||||
NAT_INIT,
|
||||
NAT_SETUP_DONE,
|
||||
NAT_SUCCESS,
|
||||
NAT_NOT_SUCCEEDED,
|
||||
NAT_FAILED,
|
||||
RELAY_INIT,
|
||||
RELAY_SUCCESS,
|
||||
RELAY_FAILED;
|
||||
|
||||
private String message;
|
||||
|
||||
BootstrapState() {
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -17,13 +17,66 @@
|
|||
|
||||
package io.bitsquare.network;
|
||||
|
||||
public interface Node {
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
String getId();
|
||||
public final class Node {
|
||||
public static final int DEFAULT_PORT = 5000;
|
||||
|
||||
String getIp();
|
||||
private final String id;
|
||||
private final String ip;
|
||||
private final int port;
|
||||
|
||||
int getPort();
|
||||
private Node(String id, String ip, int port) {
|
||||
this.id = id;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public static Node at(String id, String ip) {
|
||||
return Node.at(id, ip, DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public static Node at(String id, String ip, int port) {
|
||||
return new Node(id, ip, port);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object)
|
||||
return true;
|
||||
|
||||
if (object == null || getClass() != object.getClass())
|
||||
return false;
|
||||
|
||||
Node that = (Node) object;
|
||||
return Objects.equal(this.id, that.id) &&
|
||||
Objects.equal(this.ip, that.ip) &&
|
||||
Objects.equal(this.port, that.port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id, ip, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(Node.class.getSimpleName())
|
||||
.add("id", id)
|
||||
.add("ip", ip)
|
||||
.add("port", port)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,27 +75,27 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
futurePut.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
// deactivate it for the moment until the port forwarding bug is fixed
|
||||
// if (future.isSuccess()) {
|
||||
Platform.runLater(() -> {
|
||||
resultHandler.handleResult();
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.error("Added offer to DHT with ID: " + ((Offer) offerDataObject).getId());
|
||||
listener.onOfferAdded((Offer) offerDataObject);
|
||||
if (isSuccess(future)) {
|
||||
Platform.runLater(() -> {
|
||||
resultHandler.handleResult();
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.error("Added offer to DHT with ID: " + offerDataObject);
|
||||
listener.onOfferAdded((Offer) offerDataObject);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Add offer to DHT failed: " + e.getMessage());
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Add offer to DHT failed: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
writeInvalidationTimestampToDHT(locationKey);
|
||||
log.trace("Add offer to DHT was successful. Added data: [locationKey: " + locationKey +
|
||||
", value: " + offerData + "]");
|
||||
});
|
||||
writeInvalidationTimestampToDHT(locationKey);
|
||||
log.trace("Add offer to DHT was successful. Added data: [locationKey: " + locationKey +
|
||||
", value: " + offerData + "]");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,25 +124,25 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
futureRemove.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
// deactivate it for the moment until the port forwarding bug is fixed
|
||||
// if (future.isSuccess()) {
|
||||
Platform.runLater(() -> {
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.trace("Remove offer from DHT was successful. Removed data: [key: " +
|
||||
locationKey + ", " +
|
||||
"offer: " + (Offer) offerDataObject + "]");
|
||||
listener.onOfferRemoved((Offer) offerDataObject);
|
||||
if (isSuccess(future)) {
|
||||
Platform.runLater(() -> {
|
||||
offerRepositoryListeners.stream().forEach(listener -> {
|
||||
try {
|
||||
Object offerDataObject = offerData.object();
|
||||
if (offerDataObject instanceof Offer) {
|
||||
log.trace("Remove offer from DHT was successful. Removed data: [key: " +
|
||||
locationKey + ", " +
|
||||
"offer: " + (Offer) offerDataObject + "]");
|
||||
listener.onOfferRemoved((Offer) offerDataObject);
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Remove offer from DHT failed. Error: " + e.getMessage());
|
||||
}
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Remove offer from DHT failed. Error: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
writeInvalidationTimestampToDHT(locationKey);
|
||||
});
|
||||
writeInvalidationTimestampToDHT(locationKey);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -163,7 +163,7 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
futureGet.addListener(new BaseFutureAdapter<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception {
|
||||
if (baseFuture.isSuccess()) {
|
||||
if (isSuccess(baseFuture)) {
|
||||
final Map<Number640, Data> dataMap = futureGet.dataMap();
|
||||
final List<Offer> offers = new ArrayList<>();
|
||||
if (dataMap != null) {
|
||||
|
@ -228,7 +228,7 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
putFuture.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (putFuture.isSuccess())
|
||||
if (isSuccess(putFuture))
|
||||
log.trace("Update invalidationTimestamp to DHT was successful. TimeStamp=" +
|
||||
invalidationTimestamp.get());
|
||||
else
|
||||
|
@ -255,7 +255,7 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
getFuture.addListener(new BaseFutureListener<BaseFuture>() {
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception {
|
||||
if (getFuture.isSuccess()) {
|
||||
if (isSuccess(getFuture)) {
|
||||
Data data = getFuture.data();
|
||||
if (data != null && data.object() instanceof Long) {
|
||||
final Object object = data.object();
|
||||
|
@ -265,8 +265,8 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
invalidationTimestamp.set(timeStamp);
|
||||
});
|
||||
}
|
||||
else {
|
||||
//log.error("Get invalidationTimestamp from DHT failed. Data = " + data);
|
||||
else if (data != null) {
|
||||
log.error("Get invalidationTimestamp from DHT failed. Data = " + data);
|
||||
}
|
||||
}
|
||||
else if (getFuture.data() == null) {
|
||||
|
@ -290,4 +290,9 @@ class TomP2POfferRepository implements OfferRepository {
|
|||
return Number160.createHash(locationKey + "invalidated");
|
||||
}
|
||||
|
||||
// Isolate the success handling as there is bug in port forwarding mode
|
||||
private boolean isSuccess(BaseFuture baseFuture) {
|
||||
// return baseFuture.isSuccess();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,13 @@
|
|||
<logger name="io.bitsquare" level="TRACE"/>
|
||||
|
||||
<logger name="org.bitcoinj" level="WARN"/>
|
||||
<logger name="net.tomp2p" level="WARN"/>
|
||||
<logger name="net.tomp2p" level="TRACE"/>
|
||||
|
||||
|
||||
<logger name="net.tomp2p.message.Encoder" level="WARN"/>
|
||||
<logger name="net.tomp2p.message.Decoder" level="WARN"/>
|
||||
<logger name="net.tomp2p.message.MessageHeaderCodec" level="WARN"/>
|
||||
|
||||
|
||||
<logger name="io.netty.util" level="WARN"/>
|
||||
<logger name="io.netty.channel" level="WARN"/>
|
||||
|
@ -37,8 +43,8 @@
|
|||
<logger name="io.bitsquare.gui.util.Profiler" level="TRACE"/>
|
||||
|
||||
|
||||
<logger name=" org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||
<logger name=" org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
|
||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||
<logger name="org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
|
||||
|
||||
<!--
|
||||
<logger name="org.bitcoinj.core.Wallet" level="OFF"/>
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
* 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.msg;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.tomp2p.dht.FutureGet;
|
||||
import net.tomp2p.dht.FuturePut;
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.dht.StorageLayer;
|
||||
import net.tomp2p.dht.StorageMemory;
|
||||
import net.tomp2p.futures.FutureDirect;
|
||||
import net.tomp2p.futures.FutureDiscover;
|
||||
import net.tomp2p.nat.FutureNAT;
|
||||
import net.tomp2p.nat.FutureRelayNAT;
|
||||
import net.tomp2p.nat.PeerBuilderNAT;
|
||||
import net.tomp2p.nat.PeerNAT;
|
||||
import net.tomp2p.p2p.Peer;
|
||||
import net.tomp2p.p2p.PeerBuilder;
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import net.tomp2p.storage.Data;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BasicUsecasesInLANTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(BasicUsecasesInLANTest.class);
|
||||
|
||||
private final static String SERVER_ID = "localhost";
|
||||
private final static String SERVER_IP = "127.0.0.1";
|
||||
private final static int SERVER_PORT = 5000;
|
||||
|
||||
private final static String CLIENT_1_ID = "alice";
|
||||
private final static String CLIENT_2_ID = "bob";
|
||||
private final static int CLIENT_1_PORT = 6510;
|
||||
private final static int CLIENT_2_PORT = 6511;
|
||||
|
||||
private Thread serverThread;
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception {
|
||||
serverThread = new Thread(() -> {
|
||||
Peer peer = null;
|
||||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(SERVER_ID)).ports(SERVER_PORT).start();
|
||||
log.debug("peer started.");
|
||||
while (true) {
|
||||
for (PeerAddress pa : peer.peerBean().peerMap().all()) {
|
||||
log.debug("peer online (TCP):" + pa);
|
||||
}
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
if (peer != null)
|
||||
peer.shutdown().awaitUninterruptibly();
|
||||
} catch (IOException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
});
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception {
|
||||
serverThread.interrupt();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testBootstrap() throws Exception {
|
||||
PeerDHT peerDHT = startClient(CLIENT_1_ID, CLIENT_1_PORT);
|
||||
assertEquals(CLIENT_1_PORT, peerDHT.peerAddress().tcpPort());
|
||||
assertEquals(CLIENT_1_PORT, peerDHT.peerAddress().udpPort());
|
||||
peerDHT.shutdown().awaitUninterruptibly();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDHT() throws Exception {
|
||||
PeerDHT peer1DHT = startClient(CLIENT_1_ID, CLIENT_1_PORT);
|
||||
PeerDHT peer2DHT = startClient(CLIENT_2_ID, CLIENT_2_PORT);
|
||||
|
||||
FuturePut futurePut1 = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
// why fails that?
|
||||
//assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FutureGet futureGet2 = peer1DHT.get(Number160.createHash("key")).start();
|
||||
futureGet2.awaitUninterruptibly();
|
||||
assertTrue(futureGet2.isSuccess());
|
||||
assertNotNull(futureGet2.data());
|
||||
assertEquals("hallo1", futureGet2.data().object());
|
||||
|
||||
peer1DHT.shutdown().awaitUninterruptibly();
|
||||
peer2DHT.shutdown().awaitUninterruptibly();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSendDirect() throws Exception {
|
||||
PeerDHT peer1DHT = startClient(CLIENT_1_ID, CLIENT_1_PORT);
|
||||
PeerDHT peer2DHT = startClient(CLIENT_2_ID, CLIENT_2_PORT);
|
||||
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
final StringBuilder result = new StringBuilder();
|
||||
peer2DHT.peer().objectDataReply((sender, request) -> {
|
||||
countDownLatch.countDown();
|
||||
result.append(String.valueOf(request));
|
||||
return null;
|
||||
});
|
||||
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(peer2DHT.peerAddress()).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
countDownLatch.await(1, TimeUnit.SECONDS);
|
||||
if (countDownLatch.getCount() > 0)
|
||||
Assert.fail("The test method did not complete successfully!");
|
||||
|
||||
peer1DHT.shutdown().awaitUninterruptibly();
|
||||
peer2DHT.shutdown().awaitUninterruptibly();
|
||||
|
||||
assertEquals("hallo", result.toString());
|
||||
}
|
||||
|
||||
|
||||
private PeerDHT startClient(String clientId, int clientPort) throws Exception {
|
||||
try {
|
||||
Peer peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).behindFirewall().start();
|
||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(new StorageMemory())).start();
|
||||
|
||||
PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(SERVER_ID), SERVER_IP, SERVER_PORT,
|
||||
SERVER_PORT);
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
||||
futureDiscover.awaitUninterruptibly();
|
||||
if (futureDiscover.isSuccess()) {
|
||||
log.info("Discover with direct connection successful. Address = " + futureDiscover.peerAddress());
|
||||
return peerDHT;
|
||||
}
|
||||
else {
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
futureNAT.awaitUninterruptibly();
|
||||
if (futureNAT.isSuccess()) {
|
||||
log.info("Automatic port forwarding is setup. Address = " +
|
||||
futureNAT.peerAddress());
|
||||
return peerDHT;
|
||||
}
|
||||
else {
|
||||
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(futureDiscover, futureNAT);
|
||||
futureRelayNAT.awaitUninterruptibly();
|
||||
if (futureRelayNAT.isSuccess()) {
|
||||
log.info("Bootstrap using relay successful. Address = " +
|
||||
peer.peerAddress());
|
||||
futureRelayNAT.shutdown();
|
||||
peer.shutdown().awaitUninterruptibly();
|
||||
return peerDHT;
|
||||
}
|
||||
else {
|
||||
log.error("Bootstrap using relay failed " + futureRelayNAT.failedReason());
|
||||
Assert.fail("Bootstrap using relay failed " + futureRelayNAT.failedReason());
|
||||
futureRelayNAT.shutdown();
|
||||
peer.shutdown().awaitUninterruptibly();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Bootstrap in relay mode failed " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
Assert.fail("Bootstrap in relay mode failed " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
74
src/test/java/io/bitsquare/msg/SeedNodeForTesting.java
Normal file
74
src/test/java/io/bitsquare/msg/SeedNodeForTesting.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.msg;
|
||||
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.nat.PeerBuilderNAT;
|
||||
import net.tomp2p.p2p.Peer;
|
||||
import net.tomp2p.p2p.PeerBuilder;
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Used for testing with {@link TomP2PTests}
|
||||
*/
|
||||
public class SeedNodeForTesting {
|
||||
private static final Logger log = LoggerFactory.getLogger(SeedNodeForTesting.class);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Define your seed node IP and port
|
||||
// "127.0.0.1" for localhost or SEED_ID_WAN_1
|
||||
new SeedNodeForTesting().startSeedNode("localhost", Node.DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public Thread startSeedNode(String seedNodeId, int seedNodePort) {
|
||||
Thread thread = new Thread(() -> {
|
||||
Peer peer = null;
|
||||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(seedNodeId)).ports(seedNodePort).start();
|
||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).start();
|
||||
peerDHT.peer().objectDataReply((sender, request) -> {
|
||||
log.trace("received request: ", request.toString());
|
||||
return "pong";
|
||||
});
|
||||
|
||||
new PeerBuilderNAT(peer).start();
|
||||
|
||||
log.debug("SeedNode started.");
|
||||
for (; ; ) {
|
||||
for (PeerAddress pa : peer.peerBean().peerMap().all()) {
|
||||
log.debug("peer online:" + pa);
|
||||
}
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (peer != null)
|
||||
peer.shutdown().awaitUninterruptibly();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
return thread;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,8 +17,14 @@
|
|||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
import io.bitsquare.util.Repeat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -46,6 +52,7 @@ import net.tomp2p.storage.Data;
|
|||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -57,132 +64,64 @@ import static org.junit.Assert.*;
|
|||
* Test bootstrapping, DHT operations like put/get/add/remove and sendDirect in both LAN and WAN environment
|
||||
* Test scenarios in direct connection, auto port forwarding or relay mode.
|
||||
* <p>
|
||||
* The seed node code is in startSeedNode.
|
||||
* The start a seed node code use the {@link SeedNodeForTesting} class.
|
||||
* <p>
|
||||
* To configure your test environment edit the static fields for id, IP and port.
|
||||
* In the configure method and the connectionType you can define your test scenario further.
|
||||
* In the configure method and the connectionType you can define your test scenario.
|
||||
*/
|
||||
|
||||
//@Ignore
|
||||
@Ignore
|
||||
public class TomP2PTests {
|
||||
private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Configure
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Setup your seed node
|
||||
private final static String SEED_ID_WAN_1 = "digitalocean1.bitsquare.io";
|
||||
private final static String SEED_IP_WAN_1 = "188.226.179.109";
|
||||
private final static int SEED_PORT_WAN_1 = 5000;
|
||||
|
||||
// Setup a second seed node used in some tests
|
||||
private final static String SEED_ID_WAN_2 = "digitalocean2.bitsquare.io";
|
||||
private final static String SEED_IP_WAN_2 = "188.226.179.109";
|
||||
private final static int SEED_PORT_WAN_2 = 5001;
|
||||
|
||||
// new Ports().tcpPort() returns a random port
|
||||
private final static int CLIENT_1_PORT = new Ports().tcpPort();
|
||||
private final static int CLIENT_2_PORT = new Ports().tcpPort();
|
||||
private enum ConnectionType {
|
||||
UNKNOWN, DIRECT, NAT, RELAY
|
||||
}
|
||||
|
||||
// If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN
|
||||
private final ConnectionType forcedConnectionType = ConnectionType.NAT;
|
||||
private static final ConnectionType FORCED_CONNECTION_TYPE = ConnectionType.DIRECT;
|
||||
|
||||
// Typically you run the seed node in localhost to test direct connection.
|
||||
// If you have a setup where you are not behind a router you can also use a WAN side seed node.
|
||||
private static final Node BOOTSTRAP_NODE =
|
||||
(FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) ? BootstrapNodes.LOCALHOST : BootstrapNodes.DIGITAL_OCEAN_1;
|
||||
|
||||
private static final PeerAddress BOOTSTRAP_NODE_ADDRESS;
|
||||
|
||||
static {
|
||||
try {
|
||||
BOOTSTRAP_NODE_ADDRESS = new PeerAddress(
|
||||
Number160.createHash(BOOTSTRAP_NODE.getId()),
|
||||
BOOTSTRAP_NODE.getIp(), BOOTSTRAP_NODE.getPort(), BOOTSTRAP_NODE.getPort());
|
||||
} catch (UnknownHostException ex) {
|
||||
throw new RuntimeException(BOOTSTRAP_NODE.toString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
// If cache is used tests get faster as it doesn't create and bootstrap a new node at every test.
|
||||
// Need to observe if it can have some side effects.
|
||||
private static final boolean CACHE_CLIENTS = true;
|
||||
|
||||
// Use to stress tests by repeating them
|
||||
private static final int STRESS_TEST_COUNT = 1;
|
||||
|
||||
// need to be static to keep them during tests
|
||||
private final static Map<String, Peer> cachedPeers = new HashMap<>();
|
||||
|
||||
private PeerDHT peer1DHT;
|
||||
private PeerDHT peer2DHT;
|
||||
private int client1Port;
|
||||
private int client2Port;
|
||||
private ConnectionType resolvedConnectionType;
|
||||
|
||||
@Before
|
||||
public void configure() {
|
||||
// Typically you run the seed node in localhost to test direct connection.
|
||||
// If you have a setup where you are not behind a router you can also use a WAN side seed node.
|
||||
if (forcedConnectionType == ConnectionType.DIRECT) {
|
||||
seedId = "localhost";
|
||||
seedIP = "127.0.0.1";
|
||||
seedPort = 5000;
|
||||
}
|
||||
else {
|
||||
seedId = SEED_ID_WAN_1;
|
||||
seedIP = SEED_IP_WAN_1;
|
||||
seedPort = SEED_PORT_WAN_1;
|
||||
}
|
||||
|
||||
// Only in NAT mode we have to deal with that bug.
|
||||
if (forcedConnectionType == ConnectionType.NAT || resolvedConnectionType == ConnectionType.NAT)
|
||||
ignoreSuccessTests = true;
|
||||
public void setUp() {
|
||||
client1Port = getNewRandomPort();
|
||||
client2Port = getNewRandomPort();
|
||||
}
|
||||
|
||||
// In port forwarding mode the isSuccess returns false, but the DHT operations succeeded.
|
||||
// Needs investigation why. Will be removed as far its fixed.
|
||||
private boolean ignoreSuccessTests = false;
|
||||
|
||||
// If cache is used tests get faster as it doesn't create and bootstrap a new node at every test.
|
||||
// Need to observe if it can have some side effects.
|
||||
private boolean cacheClients = true;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private fields
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private enum ConnectionType {
|
||||
UNKNOWN,
|
||||
DIRECT,
|
||||
NAT,
|
||||
RELAY
|
||||
}
|
||||
|
||||
private final static Map<String, Peer> cachedPeers = new HashMap<>();
|
||||
private String seedId;
|
||||
private String seedIP;
|
||||
private int seedPort;
|
||||
private PeerDHT peer1DHT;
|
||||
private PeerDHT peer2DHT;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Seed node
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Define your seed node IP and port
|
||||
// "127.0.0.1" for localhost or SEED_ID_WAN_1
|
||||
new TomP2PTests().startSeedNode("127.0.0.1", 5000);
|
||||
}
|
||||
|
||||
public Thread startSeedNode(String seedNodeId, int seedNodePort) {
|
||||
Thread thread = new Thread(() -> {
|
||||
Peer peer = null;
|
||||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(seedNodeId)).ports(seedNodePort).start();
|
||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).start();
|
||||
peerDHT.peer().objectDataReply((sender, request) -> {
|
||||
log.trace("received request: ", request.toString());
|
||||
return "pong";
|
||||
});
|
||||
|
||||
new PeerBuilderNAT(peer).start();
|
||||
|
||||
log.debug("peer started.");
|
||||
for (; ; ) {
|
||||
for (PeerAddress pa : peer.peerBean().peerMap().all()) {
|
||||
log.debug("peer online (TCP):" + pa);
|
||||
}
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (peer != null)
|
||||
peer.shutdown().awaitUninterruptibly();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
if (!cacheClients) {
|
||||
public void tearDown() {
|
||||
if (!CACHE_CLIENTS) {
|
||||
if (peer1DHT != null)
|
||||
peer1DHT.shutdown().awaitUninterruptibly();
|
||||
if (peer2DHT != null)
|
||||
|
@ -191,87 +130,95 @@ public class TomP2PTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void bootstrapInUnknownMode() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.UNKNOWN)
|
||||
assertNotNull(bootstrapInUnknownMode("node_1", CLIENT_1_PORT));
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.UNKNOWN)
|
||||
assertNotNull(bootstrapInUnknownMode("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapDirectConnection() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.DIRECT)
|
||||
assertNotNull(bootstrapDirectConnection("node_1", CLIENT_1_PORT));
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT)
|
||||
assertNotNull(bootstrapDirectConnection("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapWithPortForwarding() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.NAT)
|
||||
assertNotNull(bootstrapWithPortForwarding("node_1", CLIENT_1_PORT));
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.NAT)
|
||||
assertNotNull(bootstrapWithPortForwarding("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapInRelayMode() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.RELAY)
|
||||
assertNotNull(bootstrapInRelayMode("node_1", CLIENT_1_PORT));
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY)
|
||||
assertNotNull(bootstrapInRelayMode("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testPut() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut.isSuccess());
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut.isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testPutGet() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", CLIENT_2_PORT);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("key")).start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("hallo", futureGet.data().object());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAdd() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAddGet() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", CLIENT_2_PORT);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo1")));
|
||||
|
@ -280,31 +227,33 @@ public class TomP2PTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAddRemove() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", CLIENT_2_PORT);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
Number160 contentKey = new Data("hallo1").hash();
|
||||
FutureRemove futureRemove = peer2DHT.remove(Number160.createHash("locationKey")).contentKey(contentKey).start();
|
||||
FutureRemove futureRemove = peer2DHT.remove(Number160.createHash("locationKey")).contentKey(contentKey)
|
||||
.start();
|
||||
futureRemove.awaitUninterruptibly();
|
||||
|
||||
// TODO: That fails always also with localhost seed node
|
||||
/*if (!ignoreSuccessTests)
|
||||
assertTrue(futureRemove.isSuccess());*/
|
||||
// That fails sometimes in direct mode and NAT
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureRemove.isSuccess());
|
||||
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo2")));
|
||||
|
@ -315,12 +264,12 @@ public class TomP2PTests {
|
|||
// The sendDirect operation fails in port forwarding mode because most routers does not support NAT reflections.
|
||||
// So if both clients are behind NAT they cannot send direct message to each other.
|
||||
// That will probably be fixed in a future version of TomP2P
|
||||
// In relay mode the test succeeds
|
||||
@Test
|
||||
public void testSendDirectRelay() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.RELAY || resolvedConnectionType == ConnectionType.RELAY) {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
peer2DHT = getDHTPeer("node_2", CLIENT_2_PORT);
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testSendDirectBetweenLocalPeers() throws Exception {
|
||||
if (FORCED_CONNECTION_TYPE != ConnectionType.NAT && resolvedConnectionType != ConnectionType.NAT) {
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
|
@ -331,8 +280,7 @@ public class TomP2PTests {
|
|||
return "pong";
|
||||
});
|
||||
FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection(peer2DHT.peer()
|
||||
.peerAddress(),
|
||||
500);
|
||||
.peerAddress(), 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
|
||||
|
@ -343,48 +291,36 @@ public class TomP2PTests {
|
|||
|
||||
assertEquals("hallo", result.toString());
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
log.debug(futureDirect.object().toString());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
}
|
||||
|
||||
// That test should succeed in port forwarding as we use the server seed node as receiver.
|
||||
// That test should always succeed as we use the server seed node as receiver.
|
||||
// A node can send a message to another peer which is not in the same LAN.
|
||||
@Test
|
||||
public void testSendDirectPortForwarding() throws Exception {
|
||||
if (forcedConnectionType == ConnectionType.NAT || resolvedConnectionType == ConnectionType.NAT) {
|
||||
peer1DHT = getDHTPeer("node_1", CLIENT_1_PORT);
|
||||
PeerAddress reachablePeerAddress = new PeerAddress(Number160.createHash(seedId), seedIP, seedPort,
|
||||
seedPort);
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testSendDirectToSeedNode() throws Exception {
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
|
||||
FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection(reachablePeerAddress, 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
FuturePeerConnection futurePeerConnection =
|
||||
peer1DHT.peer().createPeerConnection(BOOTSTRAP_NODE_ADDRESS, 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Bootstrapping
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Peer bootstrapDirectConnection(String clientId, int clientPort) {
|
||||
return bootstrapDirectConnection(clientId, clientPort, seedId, seedIP, seedPort);
|
||||
}
|
||||
|
||||
private Peer bootstrapDirectConnection(String clientId, int clientPort, String seedNodeId,
|
||||
String seedNodeIP, int seedNodePort) {
|
||||
final String id = clientId + clientPort;
|
||||
if (cacheClients && cachedPeers.containsKey(id)) {
|
||||
if (CACHE_CLIENTS && cachedPeers.containsKey(id)) {
|
||||
return cachedPeers.get(id);
|
||||
}
|
||||
Peer peer = null;
|
||||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).start();
|
||||
PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort,
|
||||
seedNodePort);
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start();
|
||||
futureDiscover.awaitUninterruptibly();
|
||||
if (futureDiscover.isSuccess()) {
|
||||
log.info("Discover with direct connection successful. Address = " + futureDiscover.peerAddress());
|
||||
|
@ -407,28 +343,21 @@ public class TomP2PTests {
|
|||
}
|
||||
|
||||
private Peer bootstrapWithPortForwarding(String clientId, int clientPort) {
|
||||
return bootstrapWithPortForwarding(clientId, clientPort, seedId, seedIP, seedPort);
|
||||
}
|
||||
|
||||
private Peer bootstrapWithPortForwarding(String clientId, int clientPort, String seedNodeId,
|
||||
String seedNodeIP, int seedNodePort) {
|
||||
final String id = clientId + clientPort;
|
||||
if (cacheClients && cachedPeers.containsKey(id)) {
|
||||
if (CACHE_CLIENTS && cachedPeers.containsKey(id)) {
|
||||
return cachedPeers.get(id);
|
||||
}
|
||||
Peer peer = null;
|
||||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).behindFirewall().start();
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||
PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort,
|
||||
seedNodePort);
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
futureNAT.awaitUninterruptibly();
|
||||
if (futureNAT.isSuccess()) {
|
||||
log.info("Automatic port forwarding is setup. Now we do a futureDiscover again. Address = " +
|
||||
futureNAT.peerAddress());
|
||||
futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
||||
futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start();
|
||||
futureDiscover.awaitUninterruptibly();
|
||||
if (futureDiscover.isSuccess()) {
|
||||
log.info("Discover with automatic port forwarding was successful. Address = " + futureDiscover
|
||||
|
@ -460,13 +389,8 @@ public class TomP2PTests {
|
|||
}
|
||||
|
||||
private Peer bootstrapInRelayMode(String clientId, int clientPort) {
|
||||
return bootstrapInRelayMode(clientId, clientPort, seedId, seedIP, seedPort);
|
||||
}
|
||||
|
||||
private Peer bootstrapInRelayMode(String clientId, int clientPort, String seedNodeId,
|
||||
String seedNodeIP, int seedNodePort) {
|
||||
final String id = clientId + clientPort;
|
||||
if (cacheClients && cachedPeers.containsKey(id)) {
|
||||
if (CACHE_CLIENTS && cachedPeers.containsKey(id)) {
|
||||
return cachedPeers.get(id);
|
||||
}
|
||||
|
||||
|
@ -474,9 +398,7 @@ public class TomP2PTests {
|
|||
try {
|
||||
peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).behindFirewall().start();
|
||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||
PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort,
|
||||
seedNodePort);
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
||||
FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start();
|
||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(futureDiscover, futureNAT);
|
||||
futureRelayNAT.awaitUninterruptibly();
|
||||
|
@ -503,61 +425,61 @@ public class TomP2PTests {
|
|||
}
|
||||
|
||||
private Peer bootstrapInUnknownMode(String clientId, int clientPort) {
|
||||
return bootstrapInUnknownMode(clientId, clientPort, seedId, seedIP, seedPort);
|
||||
}
|
||||
|
||||
private Peer bootstrapInUnknownMode(String clientId, int clientPort, String seedNodeId,
|
||||
String seedNodeIP, int seedNodePort) {
|
||||
resolvedConnectionType = ConnectionType.DIRECT;
|
||||
Peer peer = bootstrapDirectConnection(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
Peer peer = bootstrapDirectConnection(clientId, clientPort);
|
||||
if (peer != null)
|
||||
return peer;
|
||||
|
||||
resolvedConnectionType = ConnectionType.NAT;
|
||||
peer = bootstrapWithPortForwarding(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
peer = bootstrapWithPortForwarding(clientId, clientPort);
|
||||
if (peer != null)
|
||||
return peer;
|
||||
|
||||
resolvedConnectionType = ConnectionType.RELAY;
|
||||
peer = bootstrapInRelayMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
peer = bootstrapInRelayMode(clientId, clientPort);
|
||||
if (peer != null)
|
||||
return peer;
|
||||
else
|
||||
log.error("Bootstrapping in all modes failed. Check if the seed node is running. " +
|
||||
"seedNodeId= " + seedNodeId +
|
||||
"seedNodeIP= " + seedNodeIP +
|
||||
"seedNodePort= " + seedNodePort);
|
||||
log.error("Bootstrapping in all modes failed. Is bootstrap node " + BOOTSTRAP_NODE + "running?");
|
||||
|
||||
resolvedConnectionType = null;
|
||||
return peer;
|
||||
}
|
||||
|
||||
private PeerDHT getDHTPeer(String clientId, int clientPort) {
|
||||
return getDHTPeer(clientId, clientPort, seedId, seedIP, seedPort);
|
||||
}
|
||||
|
||||
private PeerDHT getDHTPeer(String clientId, int clientPort, String seedNodeId,
|
||||
String seedNodeIP, int seedNodePort) {
|
||||
Peer peer;
|
||||
if (forcedConnectionType == ConnectionType.DIRECT) {
|
||||
peer = bootstrapDirectConnection(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) {
|
||||
peer = bootstrapDirectConnection(clientId, clientPort);
|
||||
}
|
||||
else if (forcedConnectionType == ConnectionType.NAT) {
|
||||
peer = bootstrapWithPortForwarding(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
else if (FORCED_CONNECTION_TYPE == ConnectionType.NAT) {
|
||||
peer = bootstrapWithPortForwarding(clientId, clientPort);
|
||||
}
|
||||
else if (forcedConnectionType == ConnectionType.RELAY) {
|
||||
peer = bootstrapInRelayMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
else if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) {
|
||||
peer = bootstrapInRelayMode(clientId, clientPort);
|
||||
}
|
||||
else {
|
||||
peer = bootstrapInUnknownMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort);
|
||||
peer = bootstrapInUnknownMode(clientId, clientPort);
|
||||
}
|
||||
|
||||
if (peer == null)
|
||||
Assert.fail("Bootstrapping in all modes failed. Check if the seed node is running. " +
|
||||
"seedNodeId= " + seedNodeId +
|
||||
" seedNodeIP= " + seedNodeIP +
|
||||
" seedNodePort= " + seedNodePort);
|
||||
Assert.fail("Bootstrapping failed." +
|
||||
" forcedConnectionType= " + FORCED_CONNECTION_TYPE +
|
||||
" resolvedConnectionType= " + resolvedConnectionType + "." +
|
||||
" Is bootstrap node " + BOOTSTRAP_NODE + "running?");
|
||||
|
||||
return new PeerBuilderDHT(peer).start();
|
||||
}
|
||||
|
||||
private int getNewRandomPort() {
|
||||
// new Ports().tcpPort() returns a random port
|
||||
int newPort = new Ports().tcpPort();
|
||||
while (newPort == client1Port || newPort == client2Port)
|
||||
newPort = new Ports().tcpPort();
|
||||
|
||||
return newPort;
|
||||
}
|
||||
|
||||
private boolean shouldEvaluateSuccess() {
|
||||
return FORCED_CONNECTION_TYPE == ConnectionType.NAT || resolvedConnectionType == ConnectionType.NAT;
|
||||
}
|
||||
}
|
||||
|
|
54
src/test/java/io/bitsquare/network/NodeTests.java
Normal file
54
src/test/java/io/bitsquare/network/NodeTests.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.network;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class NodeTests {
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashCode() {
|
||||
Node node1a = Node.at("bitsquare1.example.com", "203.0.113.1");
|
||||
Node node1b = Node.at("bitsquare1.example.com", "203.0.113.1");
|
||||
|
||||
assertThat(node1a, equalTo(node1a));
|
||||
|
||||
assertThat(node1a, equalTo(node1b));
|
||||
assertThat(node1b, equalTo(node1a));
|
||||
|
||||
assertThat(node1a, not((Object) equalTo(null)));
|
||||
assertThat(node1a, not((Object) equalTo("not a node")));
|
||||
|
||||
assertThat(node1a, not(equalTo(Node.at("bitsquare2.example.com", node1a.getIp()))));
|
||||
assertThat(node1a, not(equalTo(Node.at(node1a.getId(), "203.0.113.2"))));
|
||||
assertThat(node1a, not(equalTo(Node.at(node1a.getId(), node1a.getIp(), Node.DEFAULT_PORT + 1))));
|
||||
|
||||
Node node2 = Node.at("bitsquare2.example.com", "203.0.113.2");
|
||||
assertThat(node1a.hashCode(), equalTo(node1b.hashCode()));
|
||||
assertThat(node1a.hashCode(), not(equalTo(node2.hashCode())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
Node node = Node.at("bitsquare1.example.com", "203.0.113.1", 5001);
|
||||
assertThat(node.toString(), equalTo("Node{id=bitsquare1.example.com, ip=203.0.113.1, port=5001}"));
|
||||
}
|
||||
}
|
38
src/test/java/io/bitsquare/util/Repeat.java
Normal file
38
src/test/java/io/bitsquare/util/Repeat.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 java.lang.annotation.ElementType;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Method-level annotation to be used in connection with {@link RepeatRule} to cause a
|
||||
* given {@link org.junit.Test} method to be repeated a specified number of times.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Repeat {
|
||||
|
||||
/**
|
||||
* Specifies the number of times to repeat the annotated {@link org.junit.Test}.
|
||||
*/
|
||||
int value();
|
||||
}
|
57
src/test/java/io/bitsquare/util/RepeatRule.java
Normal file
57
src/test/java/io/bitsquare/util/RepeatRule.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
/**
|
||||
* @see {@link Repeat}
|
||||
*/
|
||||
public class RepeatRule implements TestRule {
|
||||
|
||||
private static class RepeatStatement extends Statement {
|
||||
|
||||
private final int times;
|
||||
private final Statement statement;
|
||||
|
||||
private RepeatStatement(int times, Statement statement) {
|
||||
this.times = times;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
for (int i = 0; i < times; i++) {
|
||||
statement.evaluate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement statement, Description description) {
|
||||
Statement result = statement;
|
||||
Repeat repeat = description.getAnnotation(Repeat.class);
|
||||
if (repeat != null) {
|
||||
int times = repeat.value();
|
||||
result = new RepeatStatement(times, statement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
68
src/test/java/io/bitsquare/util/RepeatRuleTests.java
Normal file
68
src/test/java/io/bitsquare/util/RepeatRuleTests.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class RepeatRuleTests {
|
||||
|
||||
private static final int EXPECTED_COUNT = 10;
|
||||
private static int ACTUAL_BEFORE_COUNT;
|
||||
private static int ACTUAL_TEST_COUNT;
|
||||
private static int ACTUAL_AFTER_COUNT;
|
||||
|
||||
public @Rule RepeatRule repeatRule = new RepeatRule();
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTests() {
|
||||
ACTUAL_BEFORE_COUNT = 0;
|
||||
ACTUAL_TEST_COUNT = 0;
|
||||
ACTUAL_AFTER_COUNT = 0;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ACTUAL_BEFORE_COUNT++;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(EXPECTED_COUNT)
|
||||
public void shouldBeRepeated() {
|
||||
ACTUAL_TEST_COUNT++;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ACTUAL_AFTER_COUNT++;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterTests() {
|
||||
assertThat(ACTUAL_BEFORE_COUNT, equalTo(EXPECTED_COUNT));
|
||||
assertThat(ACTUAL_TEST_COUNT, equalTo(EXPECTED_COUNT));
|
||||
assertThat(ACTUAL_AFTER_COUNT, equalTo(EXPECTED_COUNT));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue