mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-18 03:10:52 -04:00
Use async handlers at Bootstrap
This commit is contained in:
parent
f75c5340d2
commit
aeb7730147
8 changed files with 216 additions and 315 deletions
|
@ -31,6 +31,7 @@ import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
|
||||||
|
import net.tomp2p.connection.Ports;
|
||||||
import net.tomp2p.peers.Number160;
|
import net.tomp2p.peers.Number160;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
|
||||||
|
@ -49,15 +50,15 @@ public class BitSquare {
|
||||||
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
||||||
|
|
||||||
private static String appName = "Bitsquare";
|
private static String appName = "Bitsquare";
|
||||||
private static int port;
|
private static int clientPort;
|
||||||
private static String interfaceHint;
|
private static String interfaceHint;
|
||||||
|
|
||||||
public static String getAppName() {
|
public static String getAppName() {
|
||||||
return appName;
|
return appName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getPort() {
|
public static int getClientPort() {
|
||||||
return port;
|
return clientPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -76,15 +77,15 @@ public class BitSquare {
|
||||||
appName = appName + "-" + namespace.getString(BitsquareArgumentParser.NAME_FLAG);
|
appName = appName + "-" + namespace.getString(BitsquareArgumentParser.NAME_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
port = BitsquareArgumentParser.PORT_DEFAULT;
|
|
||||||
if (namespace.getString(BitsquareArgumentParser.PORT_FLAG) != null) {
|
|
||||||
port = Integer.valueOf(namespace.getString(BitsquareArgumentParser.PORT_FLAG));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namespace.getString(BitsquareArgumentParser.INFHINT_FLAG) != null) {
|
if (namespace.getString(BitsquareArgumentParser.INFHINT_FLAG) != null) {
|
||||||
interfaceHint = namespace.getString(BitsquareArgumentParser.INFHINT_FLAG);
|
interfaceHint = namespace.getString(BitsquareArgumentParser.INFHINT_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int port = -1;
|
||||||
|
if (namespace.getString(BitsquareArgumentParser.PORT_FLAG) != null) {
|
||||||
|
port = Integer.valueOf(namespace.getString(BitsquareArgumentParser.PORT_FLAG));
|
||||||
|
}
|
||||||
|
|
||||||
if (namespace.getBoolean(BitsquareArgumentParser.SEED_FLAG) == true) {
|
if (namespace.getBoolean(BitsquareArgumentParser.SEED_FLAG) == true) {
|
||||||
String seedID = SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1.getId();
|
String seedID = SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1.getId();
|
||||||
if (namespace.getString(BitsquareArgumentParser.PEER_ID_FLAG) != null) {
|
if (namespace.getString(BitsquareArgumentParser.PEER_ID_FLAG) != null) {
|
||||||
|
@ -96,19 +97,22 @@ public class BitSquare {
|
||||||
final Set<PeerAddress> peerAddresses = new HashSet<PeerAddress>();
|
final Set<PeerAddress> peerAddresses = new HashSet<PeerAddress>();
|
||||||
final String sid = seedID;
|
final String sid = seedID;
|
||||||
SeedNodeAddress.StaticSeedNodeAddresses.getAllSeedNodeAddresses().forEach(a -> {
|
SeedNodeAddress.StaticSeedNodeAddresses.getAllSeedNodeAddresses().forEach(a -> {
|
||||||
if (!a.getId().equals(sid)) {
|
if (!a.getId().equals(sid)) {
|
||||||
try {
|
try {
|
||||||
peerAddresses.add(new PeerAddress(Number160.createHash(a.getId()),a.getIp(),
|
peerAddresses.add(new PeerAddress(Number160.createHash(a.getId()), a.getIp(),
|
||||||
a.getPort(), a.getPort()));
|
a.getPort(), a.getPort()));
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (UnknownHostException uhe) {
|
||||||
log.error("Unknown Host ["+a.getIp()+"]: "+uhe.getMessage());
|
log.error("Unknown Host [" + a.getIp() + "]: " + uhe.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
int serverPort = (port == -1) ? BitsquareArgumentParser.PORT_DEFAULT : port;
|
||||||
|
|
||||||
ActorRef seedNode = actorSystem.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME);
|
ActorRef seedNode = actorSystem.actorOf(DHTManager.getProps(), DHTManager.SEED_NAME);
|
||||||
Inbox inbox = Inbox.create(actorSystem);
|
Inbox inbox = Inbox.create(actorSystem);
|
||||||
inbox.send(seedNode, new InitializePeer(Number160.createHash(sid), port, interfaceHint, peerAddresses));
|
inbox.send(seedNode, new InitializePeer(Number160.createHash(sid), serverPort, interfaceHint,
|
||||||
|
peerAddresses));
|
||||||
|
|
||||||
Thread seedNodeThread = new Thread(() -> {
|
Thread seedNodeThread = new Thread(() -> {
|
||||||
Boolean quit = false;
|
Boolean quit = false;
|
||||||
|
@ -139,7 +143,8 @@ public class BitSquare {
|
||||||
seedNodeThread.start();
|
seedNodeThread.start();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// We use a random port for the client if no port is passed to the application
|
||||||
|
clientPort = (port == -1) ? new Ports().tcpPort() : port;
|
||||||
Application.launch(BitSquareUI.class, args);
|
Application.launch(BitSquareUI.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,8 +118,8 @@ class StaticSeedNodeAddressesProvider implements Provider<SeedNodeAddress.Static
|
||||||
String seedNodeFromConfig = BitSquareModule.properties.getProperty("defaultSeedNode");
|
String seedNodeFromConfig = BitSquareModule.properties.getProperty("defaultSeedNode");
|
||||||
|
|
||||||
// Set default
|
// Set default
|
||||||
SeedNodeAddress.StaticSeedNodeAddresses seedNode = SeedNodeAddress.StaticSeedNodeAddresses.LOCALHOST;
|
//SeedNodeAddress.StaticSeedNodeAddresses seedNode = SeedNodeAddress.StaticSeedNodeAddresses.LOCALHOST;
|
||||||
//SeedNodeAddress.StaticSeedNodeAddresses seedNode = SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1;
|
SeedNodeAddress.StaticSeedNodeAddresses seedNode = SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1;
|
||||||
|
|
||||||
// if defined in config we override the above
|
// if defined in config we override the above
|
||||||
// if (seedNodeFromConfig != null)
|
// if (seedNodeFromConfig != null)
|
||||||
|
@ -146,8 +146,8 @@ class NetworkParametersProvider implements Provider<NetworkParameters> {
|
||||||
|
|
||||||
// Set default
|
// Set default
|
||||||
// String networkType= WalletFacade.MAIN_NET;
|
// String networkType= WalletFacade.MAIN_NET;
|
||||||
//String networkType = WalletFacade.TEST_NET;
|
String networkType = WalletFacade.TEST_NET;
|
||||||
String networkType = WalletFacade.REG_TEST_NET;
|
//String networkType = WalletFacade.REG_TEST_NET;
|
||||||
|
|
||||||
if (networkTypeFromConfig != null)
|
if (networkTypeFromConfig != null)
|
||||||
networkType = networkTypeFromConfig;
|
networkType = networkTypeFromConfig;
|
||||||
|
|
|
@ -107,7 +107,7 @@ class MainModel extends UIModel {
|
||||||
// For testing with the serverside seednode we need the BootstrappedPeerFactory which gets started form
|
// For testing with the serverside seednode we need the BootstrappedPeerFactory which gets started form
|
||||||
// messageFacade.init
|
// messageFacade.init
|
||||||
|
|
||||||
messageFacade.init(BitSquare.getPort(), new BootstrapListener() {
|
messageFacade.init(BitSquare.getClientPort(), new BootstrapListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCompleted() {
|
public void onCompleted() {
|
||||||
messageFacadeInited = true;
|
messageFacadeInited = true;
|
||||||
|
|
|
@ -44,7 +44,6 @@ import net.tomp2p.dht.PeerDHT;
|
||||||
import net.tomp2p.dht.StorageLayer;
|
import net.tomp2p.dht.StorageLayer;
|
||||||
import net.tomp2p.futures.BaseFuture;
|
import net.tomp2p.futures.BaseFuture;
|
||||||
import net.tomp2p.futures.BaseFutureListener;
|
import net.tomp2p.futures.BaseFutureListener;
|
||||||
import net.tomp2p.futures.FutureBootstrap;
|
|
||||||
import net.tomp2p.futures.FutureDiscover;
|
import net.tomp2p.futures.FutureDiscover;
|
||||||
import net.tomp2p.nat.FutureNAT;
|
import net.tomp2p.nat.FutureNAT;
|
||||||
import net.tomp2p.nat.FutureRelayNAT;
|
import net.tomp2p.nat.FutureRelayNAT;
|
||||||
|
@ -56,7 +55,6 @@ import net.tomp2p.peers.Number160;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import net.tomp2p.peers.PeerMapChangeListener;
|
import net.tomp2p.peers.PeerMapChangeListener;
|
||||||
import net.tomp2p.peers.PeerStatatistic;
|
import net.tomp2p.peers.PeerStatatistic;
|
||||||
import net.tomp2p.relay.FutureRelay;
|
|
||||||
import net.tomp2p.storage.Storage;
|
import net.tomp2p.storage.Storage;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -67,7 +65,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import static io.bitsquare.msg.SeedNodeAddress.StaticSeedNodeAddresses;
|
import static io.bitsquare.msg.SeedNodeAddress.StaticSeedNodeAddresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DHT peer and bootstrap to a seed node
|
* Creates a DHT peer and bootstrap to the network via a seed node
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
public class BootstrappedPeerFactory {
|
public class BootstrappedPeerFactory {
|
||||||
|
@ -116,88 +114,6 @@ public class BootstrappedPeerFactory {
|
||||||
Peer peer = new PeerBuilder(keyPair).ports(port).behindFirewall().start();
|
Peer peer = new PeerBuilder(keyPair).ports(port).behindFirewall().start();
|
||||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(storage)).start();
|
PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer(storage)).start();
|
||||||
|
|
||||||
PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeAddress.getId()),
|
|
||||||
InetAddress.getByName(seedNodeAddress.getIp()),
|
|
||||||
seedNodeAddress.getPort(),
|
|
||||||
seedNodeAddress.getPort());
|
|
||||||
FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
|
||||||
futureDiscover.awaitUninterruptibly();
|
|
||||||
if (futureDiscover.isSuccess()) {
|
|
||||||
log.info("Discover with direct connection successful. Address = " + futureDiscover.peerAddress());
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
|
|
||||||
// settableFuture.set(peerDHT);
|
|
||||||
// return settableFuture;
|
|
||||||
|
|
||||||
futureDiscover = peer.discover().peerAddress(masterNodeAddress).start();
|
|
||||||
futureDiscover.awaitUninterruptibly();
|
|
||||||
if (futureDiscover.isSuccess()) {
|
|
||||||
log.info("Discover with automatic port forwarding successful. Address = " + futureDiscover
|
|
||||||
.peerAddress());
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.error("Discover with automatic port forwarding failed " + futureDiscover.failedReason());
|
|
||||||
settableFuture.setException(new Exception("Discover with automatic port forwarding failed " +
|
|
||||||
futureDiscover.failedReason()));
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// consider to use a dedicated relay node (Pawan Kumar use that approach)
|
|
||||||
// PeerAddress relay = new PeerAddress(new Number160(new Random(43L)),
|
|
||||||
// InetAddress.getByName("relay-ip"),
|
|
||||||
// 5000, 5000);
|
|
||||||
// peerNAT.addRelay(relay);
|
|
||||||
|
|
||||||
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(futureDiscover, futureNAT);
|
|
||||||
futureRelayNAT.awaitUninterruptibly();
|
|
||||||
if (futureRelayNAT.isSuccess()) {
|
|
||||||
log.info("Bootstrap using relay successful. Address = " +
|
|
||||||
futureDiscover.peerAddress());
|
|
||||||
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.error("Bootstrap using relay failed " + futureRelayNAT.failedReason());
|
|
||||||
settableFuture.setException(new Exception("Bootstrap in relay mode failed " + futureRelayNAT
|
|
||||||
.failedReason()));
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Bootstrap in relay mode failed " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
settableFuture.setException(e);
|
|
||||||
return settableFuture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<PeerDHT> startOld(int port) {
|
|
||||||
try {
|
|
||||||
/* ChannelServerConficuration csc = PeerBuilder.createDefaultChannelServerConfiguration();
|
|
||||||
csc.idleTCPSeconds(20).idleUDPSeconds(20).connectionTimeoutTCPMillis(20000);
|
|
||||||
Peer peer = new PeerBuilder(keyPair).ports(port).channelServerConfiguration(csc).start();*/
|
|
||||||
Peer peer = new PeerBuilder(keyPair).ports(port).portsExternal(port).start();
|
|
||||||
/* Peer peer = new PeerBuilder(keyPair).ports(port).portsExternal(port)
|
|
||||||
.channelServerConfiguration(csc).start();
|
|
||||||
*/
|
|
||||||
PeerDHT peerDHT = new PeerBuilderDHT(peer).storageLayer(new StorageLayer
|
|
||||||
(storage)).start();
|
|
||||||
|
|
||||||
peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() {
|
peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void peerInserted(PeerAddress peerAddress, boolean verified) {
|
public void peerInserted(PeerAddress peerAddress, boolean verified) {
|
||||||
|
@ -211,21 +127,21 @@ public class BootstrappedPeerFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void peerUpdated(PeerAddress peerAddress, PeerStatatistic peerStatistics) {
|
public void peerUpdated(PeerAddress peerAddress, PeerStatatistic peerStatistics) {
|
||||||
//log.debug("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics);
|
// log.debug("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// We save last successful bootstrap method.
|
// We save last successful bootstrap method.
|
||||||
// Reset it to "default" after 5 start ups.
|
// Reset it to "default" after 5 start ups.
|
||||||
Object lastSuccessfulBootstrapCounterObject = persistence.read(this, "lastSuccessfulBootstrapCounter");
|
Object bootstrapCounterObject = persistence.read(this, "bootstrapCounter");
|
||||||
int lastSuccessfulBootstrapCounter = 0;
|
int bootstrapCounter = 0;
|
||||||
if (lastSuccessfulBootstrapCounterObject != null)
|
if (bootstrapCounterObject instanceof Integer)
|
||||||
lastSuccessfulBootstrapCounter = (int) lastSuccessfulBootstrapCounterObject;
|
bootstrapCounter = (int) bootstrapCounterObject + 1;
|
||||||
|
|
||||||
if (lastSuccessfulBootstrapCounter > 5)
|
if (bootstrapCounter > 5)
|
||||||
persistence.write(this, "lastSuccessfulBootstrap", "default");
|
persistence.write(this, "lastSuccessfulBootstrap", "default");
|
||||||
|
|
||||||
persistence.write(this, "lastSuccessfulBootstrapCounter", lastSuccessfulBootstrapCounter + 1);
|
persistence.write(this, "bootstrapCounter", bootstrapCounter);
|
||||||
|
|
||||||
|
|
||||||
String lastSuccessfulBootstrap = (String) persistence.read(this, "lastSuccessfulBootstrap");
|
String lastSuccessfulBootstrap = (String) persistence.read(this, "lastSuccessfulBootstrap");
|
||||||
|
@ -233,36 +149,157 @@ public class BootstrappedPeerFactory {
|
||||||
lastSuccessfulBootstrap = "default";
|
lastSuccessfulBootstrap = "default";
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
lastSuccessfulBootstrap = "default";
|
// lastSuccessfulBootstrap = "default";
|
||||||
|
|
||||||
log.debug("lastSuccessfulBootstrap = " + lastSuccessfulBootstrap);
|
log.debug("lastSuccessfulBootstrap = " + lastSuccessfulBootstrap);
|
||||||
|
FutureDiscover futureDiscover;
|
||||||
switch (lastSuccessfulBootstrap) {
|
switch (lastSuccessfulBootstrap) {
|
||||||
case "relay":
|
case "relay":
|
||||||
PeerNAT nodeBehindNat = new PeerBuilderNAT(peerDHT.peer()).start();
|
futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||||
bootstrapWithRelay(peerDHT, nodeBehindNat);
|
PeerNAT peerNAT = new PeerBuilderNAT(peerDHT.peer()).start();
|
||||||
|
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||||
|
bootstrapWithRelay(peerDHT, peerNAT, futureDiscover, futureNAT);
|
||||||
break;
|
break;
|
||||||
case "startPortForwarding":
|
case "portForwarding":
|
||||||
FutureDiscover futureDiscover =
|
futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
||||||
peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
tryPortForwarding(peerDHT, futureDiscover);
|
||||||
bootstrapWithPortForwarding(peerDHT, futureDiscover);
|
|
||||||
break;
|
break;
|
||||||
case "default":
|
case "default":
|
||||||
default:
|
default:
|
||||||
bootstrap(peerDHT);
|
discover(peerDHT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Exception: " + e);
|
setState("Cannot create peer with port: " + port + ". Exeption: " + e, false);
|
||||||
settableFuture.setException(e);
|
settableFuture.setException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return settableFuture;
|
return settableFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1. Attempt: Try to discover our outside visible address
|
||||||
|
private void discover(PeerDHT peerDHT) {
|
||||||
|
FutureDiscover futureDiscover = peerDHT.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());
|
||||||
|
settableFuture.set(peerDHT);
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn("Discover has failed. Reason: " + futureDiscover.failedReason());
|
||||||
|
setState("We are probably behind a NAT and not reachable to other peers. " +
|
||||||
|
"We try port forwarding as next step.");
|
||||||
|
tryPortForwarding(peerDHT, futureDiscover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
@Override
|
||||||
// Private
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
setState("Exception at discover: " + t.getMessage(), false);
|
||||||
|
settableFuture.setException(t);
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
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());
|
||||||
|
// we need a second discover process
|
||||||
|
discoverAfterPortForwarding(peerDHT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn("Port forwarding has failed. Reason: " + futureNAT.failedReason());
|
||||||
|
setState("Port forwarding has failed. We try to use a relay as next step.");
|
||||||
|
bootstrapWithRelay(peerDHT, peerNAT, futureDiscover, futureNAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
|
setState("Exception at port forwarding: " + t.getMessage(), false);
|
||||||
|
settableFuture.setException(t);
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
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());
|
||||||
|
settableFuture.set(peerDHT);
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "portForwarding");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState("Discover with automatic port forwarding has failed " + futureDiscover
|
||||||
|
.failedReason(), false);
|
||||||
|
settableFuture.setException(new Exception("Discover with automatic port forwarding failed " +
|
||||||
|
futureDiscover.failedReason()));
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
|
setState("Exception at discover: " + t, false);
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||||
|
settableFuture.setException(t);
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Attempt: We try to use another peer as relay
|
||||||
|
private void bootstrapWithRelay(PeerDHT peerDHT, PeerNAT peerNAT, FutureDiscover futureDiscover,
|
||||||
|
FutureNAT futureNAT) {
|
||||||
|
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 = " + futureDiscover.peerAddress());
|
||||||
|
settableFuture.set(peerDHT);
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "relay");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState("Bootstrap using relay has failed " + futureDiscover.failedReason(), false);
|
||||||
|
settableFuture.setException(new Exception("Bootstrap using relay failed " +
|
||||||
|
futureDiscover.failedReason()));
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||||
|
futureRelayNAT.shutdown();
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
|
setState("Exception at bootstrapWithRelay: " + t, false);
|
||||||
|
persistence.write(BootstrappedPeerFactory.this, "lastSuccessfulBootstrap", "default");
|
||||||
|
settableFuture.setException(t);
|
||||||
|
futureRelayNAT.shutdown();
|
||||||
|
peerDHT.shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private PeerAddress getBootstrapAddress() {
|
private PeerAddress getBootstrapAddress() {
|
||||||
try {
|
try {
|
||||||
|
@ -276,187 +313,15 @@ public class BootstrappedPeerFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bootstrap(PeerDHT peerDHT) {
|
private void setState(String state) {
|
||||||
// Check if peer is reachable from outside
|
setState(state, true);
|
||||||
FutureDiscover futureDiscover = peerDHT.peer().discover().peerAddress(getBootstrapAddress()).start();
|
|
||||||
BootstrappedPeerFactory ref = this;
|
|
||||||
futureDiscover.addListener(new BaseFutureListener<BaseFuture>() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
// We are not behind a NAT and reachable to other peers
|
|
||||||
log.debug("We are not behind a NAT and reachable to other peers: My address visible to the " +
|
|
||||||
"outside is " + futureDiscover.peerAddress());
|
|
||||||
requestBootstrapPeerMap();
|
|
||||||
setConnectionState("We are not behind a NAT and reachable to other peers: My address visible to " +
|
|
||||||
"the " +
|
|
||||||
"outside is " + futureDiscover.peerAddress());
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "default");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn("Discover has failed. Reason: " + futureDiscover.failedReason());
|
|
||||||
log.warn("We are probably behind a NAT and not reachable to other peers. We try port forwarding " +
|
|
||||||
"as next step.");
|
|
||||||
|
|
||||||
setConnectionState("We are probably behind a NAT and not reachable to other peers. We try port " +
|
|
||||||
"forwarding " +
|
|
||||||
"as next step.");
|
|
||||||
|
|
||||||
bootstrapWithPortForwarding(peerDHT, futureDiscover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
|
||||||
log.error("Exception at discover: " + t);
|
|
||||||
settableFuture.setException(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bootstrapWithPortForwarding(PeerDHT peerDHT, FutureDiscover futureDiscover) {
|
private void setState(String state, boolean isSuccess) {
|
||||||
// Assume we are behind a NAT device
|
if (isSuccess)
|
||||||
PeerNAT nodeBehindNat = new PeerBuilderNAT(peerDHT.peer()).start();
|
log.info(state);
|
||||||
|
else
|
||||||
// Try to set up port forwarding with UPNP and NATPMP if peer is not reachable
|
log.error(state);
|
||||||
FutureNAT futureNAT = nodeBehindNat.startSetupPortforwarding(futureDiscover);
|
|
||||||
BootstrappedPeerFactory ref = this;
|
|
||||||
futureNAT.addListener(new BaseFutureListener<BaseFuture>() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
// Port forwarding has succeed
|
|
||||||
log.debug("Port forwarding was successful. My address visible to the outside is " +
|
|
||||||
futureNAT.peerAddress());
|
|
||||||
requestBootstrapPeerMap();
|
|
||||||
setConnectionState("Port forwarding was successful. My address visible to the outside is " +
|
|
||||||
futureNAT.peerAddress());
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "portForwarding");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn("Port forwarding has failed. Reason: " + futureNAT.failedReason());
|
|
||||||
log.warn("We try to use a relay as next step.");
|
|
||||||
|
|
||||||
setConnectionState("We try to use a relay as next step.");
|
|
||||||
|
|
||||||
bootstrapWithRelay(peerDHT, nodeBehindNat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
|
||||||
log.error("Exception at port forwarding: " + t);
|
|
||||||
settableFuture.setException(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bootstrapWithRelay(PeerDHT peerDHT, PeerNAT nodeBehindNat) {
|
|
||||||
// Last resort: we try to use other peers as relays
|
|
||||||
|
|
||||||
// The firewalled flags have to be set, so that other peers don’t add the unreachable peer to their peer maps.
|
|
||||||
Peer peer = peerDHT.peer();
|
|
||||||
PeerAddress serverPeerAddress = peer.peerBean().serverPeerAddress();
|
|
||||||
serverPeerAddress = serverPeerAddress.changeFirewalledTCP(true).changeFirewalledUDP(true);
|
|
||||||
peer.peerBean().serverPeerAddress(serverPeerAddress);
|
|
||||||
|
|
||||||
// Find neighbors
|
|
||||||
FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(getBootstrapAddress()).start();
|
|
||||||
futureBootstrap.addListener(new BaseFutureListener<BaseFuture>() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
log.debug("Bootstrap was successful. bootstrapTo = " + futureBootstrap.bootstrapTo());
|
|
||||||
|
|
||||||
setupRelay(peerDHT, nodeBehindNat, getBootstrapAddress());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.error("Bootstrap failed. Reason:" + futureBootstrap.failedReason());
|
|
||||||
settableFuture.setException(new Exception(futureBootstrap.failedReason()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
|
||||||
log.error("Exception at bootstrap: " + t);
|
|
||||||
settableFuture.setException(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupRelay(PeerDHT peerDHT, PeerNAT nodeBehindNat, PeerAddress bootstrapAddress) {
|
|
||||||
FutureRelay futureRelay = new FutureRelay();
|
|
||||||
futureRelay.addListener(new BaseFutureListener<BaseFuture>() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
log.debug("Start setup relay was successful.");
|
|
||||||
//futureRelay.relays().forEach(e -> log.debug("remotePeer = " + e.remotePeer()));
|
|
||||||
|
|
||||||
findNeighbors2(peerDHT, bootstrapAddress);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.error("setupRelay failed. Reason: " + futureRelay.failedReason());
|
|
||||||
log.error("Bootstrap failed. We give up...");
|
|
||||||
settableFuture.setException(new Exception(futureRelay.failedReason()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
|
||||||
log.error("Exception at setup relay: " + t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*DistributedRelay distributedRelay = nodeBehindNat.startSetupRelay(futureRelay);
|
|
||||||
distributedRelay.addRelayListener((distributedRelay1, peerConnection) -> {
|
|
||||||
log.debug("startSetupRelay distributedRelay handler called " + distributedRelay1 + "/" + peerConnection);
|
|
||||||
settableFuture.setException(new Exception("startSetupRelay Failed"));
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void findNeighbors2(PeerDHT peerDHT, PeerAddress bootstrapAddress) {
|
|
||||||
// find neighbors again
|
|
||||||
FutureBootstrap futureBootstrap2 = peerDHT.peer().bootstrap().peerAddress(bootstrapAddress).start();
|
|
||||||
BootstrappedPeerFactory ref = this;
|
|
||||||
futureBootstrap2.addListener(new BaseFutureListener<BaseFuture>() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
log.debug("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2.bootstrapTo());
|
|
||||||
requestBootstrapPeerMap();
|
|
||||||
setConnectionState("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2
|
|
||||||
.bootstrapTo());
|
|
||||||
settableFuture.set(peerDHT);
|
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "relay");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.error("Bootstrap 2 failed. Reason:" + futureBootstrap2.failedReason());
|
|
||||||
log.error("We give up...");
|
|
||||||
settableFuture.setException(new Exception(futureBootstrap2.failedReason()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
|
||||||
log.error("Exception at bootstrap 2: " + t);
|
|
||||||
settableFuture.setException(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO we want to get a list of connected nodes form the seed node and save them locally for future bootstrapping
|
|
||||||
// The seed node should only be used if no other known peers are available
|
|
||||||
private void requestBootstrapPeerMap() {
|
|
||||||
log.debug("getBootstrapPeerMap");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setConnectionState(String state) {
|
|
||||||
Platform.runLater(() -> connectionState.set(state));
|
Platform.runLater(() -> connectionState.set(state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ import net.tomp2p.nat.PeerBuilderNAT;
|
||||||
import net.tomp2p.nat.PeerNAT;
|
import net.tomp2p.nat.PeerNAT;
|
||||||
import net.tomp2p.p2p.Peer;
|
import net.tomp2p.p2p.Peer;
|
||||||
import net.tomp2p.p2p.PeerBuilder;
|
import net.tomp2p.p2p.PeerBuilder;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import net.tomp2p.peers.PeerMapChangeListener;
|
||||||
|
import net.tomp2p.peers.PeerStatatistic;
|
||||||
|
|
||||||
import akka.actor.AbstractActor;
|
import akka.actor.AbstractActor;
|
||||||
import akka.actor.Props;
|
import akka.actor.Props;
|
||||||
|
@ -73,6 +76,26 @@ public class DHTManager extends AbstractActor {
|
||||||
peerDHT = new PeerBuilderDHT(peer).start();
|
peerDHT = new PeerBuilderDHT(peer).start();
|
||||||
peerNAT = new PeerBuilderNAT(peer).start();
|
peerNAT = new PeerBuilderNAT(peer).start();
|
||||||
|
|
||||||
|
peer.peerBean().peerMap().addPeerMapChangeListener(new PeerMapChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void peerInserted(PeerAddress peerAddress, boolean verified) {
|
||||||
|
log.debug("Peer inserted: peerAddress=" + peerAddress + ", " +
|
||||||
|
"verified=" + verified);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void peerRemoved(PeerAddress peerAddress, PeerStatatistic peerStatistics) {
|
||||||
|
log.debug("Peer removed: peerAddress=" + peerAddress + ", " +
|
||||||
|
"peerStatistics=" + peerStatistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void peerUpdated(PeerAddress peerAddress, PeerStatatistic peerStatistics) {
|
||||||
|
// log.debug("Peer updated: peerAddress=" + peerAddress + ",
|
||||||
|
// peerStatistics=" + peerStatistics);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
sender().tell(new PeerInitialized(peer.peerID(), ip.getPort()), self());
|
sender().tell(new PeerInitialized(peer.peerID(), ip.getPort()), self());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
log.info("The second instance has been started. If that happens at the first instance" +
|
log.info("The second instance has been started. If that happens at the first instance" +
|
||||||
|
|
|
@ -25,6 +25,15 @@ import net.sourceforge.argparse4j.inf.ArgumentParser;
|
||||||
import net.sourceforge.argparse4j.inf.ArgumentParserException;
|
import net.sourceforge.argparse4j.inf.ArgumentParserException;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
|
|
||||||
|
/*
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-s, --seed Start as DHT seed peer, no UI. (default: false)
|
||||||
|
-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 BitsquareArgumentParser {
|
public class BitsquareArgumentParser {
|
||||||
|
|
||||||
public static String SEED_FLAG = "seed";
|
public static String SEED_FLAG = "seed";
|
||||||
|
@ -39,19 +48,18 @@ public class BitsquareArgumentParser {
|
||||||
public BitsquareArgumentParser() {
|
public BitsquareArgumentParser() {
|
||||||
parser = ArgumentParsers.newArgumentParser("BitSquare")
|
parser = ArgumentParsers.newArgumentParser("BitSquare")
|
||||||
.defaultHelp(true)
|
.defaultHelp(true)
|
||||||
.description("BitSquare decentralized bitcoin exchange.");
|
.description("BitSquare - The decentralized bitcoin exchange.");
|
||||||
parser.addArgument("-s", "--" + SEED_FLAG)
|
parser.addArgument("-s", "--" + SEED_FLAG)
|
||||||
.action(Arguments.storeTrue())
|
.action(Arguments.storeTrue())
|
||||||
.help("Start as DHT seed peer, no UI.");
|
.help("Start as DHT seed peer, no UI.");
|
||||||
parser.addArgument("-d", "--" + PEER_ID_FLAG)
|
parser.addArgument("-d", "--" + PEER_ID_FLAG)
|
||||||
.setDefault(SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1.getId())
|
.setDefault(SeedNodeAddress.StaticSeedNodeAddresses.DIGITAL_OCEAN1.getId())
|
||||||
.help("Seed peer ID.");
|
.help("Seed peer ID.");
|
||||||
parser.addArgument("-p", "--"+PORT_FLAG)
|
parser.addArgument("-p", "--" + PORT_FLAG)
|
||||||
.setDefault(PORT_DEFAULT)
|
|
||||||
.help("IP port to listen on.");
|
.help("IP port to listen on.");
|
||||||
parser.addArgument("-i", "--" + INFHINT_FLAG)
|
parser.addArgument("-i", "--" + INFHINT_FLAG)
|
||||||
.help("Network interface to listen on.");
|
.help("Network interface to listen on.");
|
||||||
parser.addArgument("-n", "--"+NAME_FLAG)
|
parser.addArgument("-n", "--" + NAME_FLAG)
|
||||||
.help("Append name to application name.");
|
.help("Append name to application name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
<logger name="io.bitsquare" level="TRACE"/>
|
<logger name="io.bitsquare" level="TRACE"/>
|
||||||
|
|
||||||
<logger name="org.bitcoinj" level="INFO"/>
|
<logger name="org.bitcoinj" level="WARN"/>
|
||||||
<logger name="net.tomp2p" level="WARN"/>
|
<logger name="net.tomp2p" level="WARN"/>
|
||||||
|
|
||||||
<logger name="io.netty.util" level="WARN"/>
|
<logger name="io.netty.util" level="WARN"/>
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class DHTTestController implements Initializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
messageFacade.init(BitSquare.getPort(), new BootstrapListener() {
|
messageFacade.init(BitSquare.getClientPort(), new BootstrapListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCompleted() {
|
public void onCompleted() {
|
||||||
onMessageFacadeInitialised();
|
onMessageFacadeInitialised();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue