Merge branch 'wip-cbeams'

* wip-cbeams: (24 commits)
  Allow configurability of bitcoin network with --bitcoin.network
  Eliminate BootstrapNodes#DIGITAL_OCEAN_1_DEV
  Move comments regarding default ports to Node#DEFAULT_PORT
  Rename BootstrapNodes#{DEFAULT_BOOTSTRAP_NODE=>DEFAULT}
  Rename app.cli.{SeedNode => BootstrapNode}
  Remove dead code from UtilsDHT2.java
  Remove commented code from SeedNode
  Remove obsolete SeedNodeForTesting class
  Rename networkInterface => interface
  Eliminate the option to use TomP2P disk storage (for now)
  Expose --port command-line option
  Rename Node#{id => name}
  Allow command-line configuration of local node id and port
  Polish whitespace
  Qualify id, ip and port options with 'bootstrap.node.*'
  Extract clientPort constant
  Introduce NETWORK_INTERFACE_UNSPECIFIED contstant
  Move {MessageModule=>TomP2PMessageModule}#NETWORK_INTERFACE_KEY
  Use extracted NETWORK_INTERFACE_KEY consistently
  Polish TomP2PMessageModule#doConfigure
  ...

Conflicts:
	src/test/java/io/bitsquare/msg/TomP2PTests.java
This commit is contained in:
Chris Beams 2014-11-10 15:43:28 +01:00
commit efe6c1bec9
No known key found for this signature in database
GPG key ID: 3D214F8F5BC5ED73
22 changed files with 251 additions and 638 deletions

View file

@ -13,13 +13,10 @@
# Mac OSX:
# $HOME/Library/Application Support/Bitcoin/
# /Users/username/Library/Application Support/Bitcoin/bitcoin.conf
# /Users/username/Library/Application Support/Bitcoin/bitcoin.conf
# Supported properties:
# networkType=regtest | testnet | mainnet
# bitcoin.network=regtest | testnet | mainnet
# defaultSeedNode=localhost | server
networkType=regtest
defaultSeedNode=localhost
bitcoin.network=regtest

View file

@ -36,8 +36,6 @@ import com.google.inject.name.Names;
import java.util.Properties;
import net.tomp2p.connection.Ports;
/**
* Configures all non-UI modules necessary to run a Bitsquare application.
*/
@ -64,9 +62,6 @@ public class AppModule extends BitsquareModule {
Preconditions.checkArgument(appName != null, "App name must be non-null");
bindConstant().annotatedWith(Names.named("appName")).to(appName);
int randomPort = new Ports().tcpPort();
bindConstant().annotatedWith(Names.named("clientPort")).to(randomPort);
}
protected MessageModule messageModule() {

View file

@ -17,12 +17,15 @@
package io.bitsquare.app;
import io.bitsquare.btc.BitcoinModule;
import io.bitsquare.network.Node;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
import static io.bitsquare.app.AppModule.APP_NAME_KEY;
import static io.bitsquare.msg.MessageModule.*;
import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*;
public class ArgumentParser {
@ -33,18 +36,28 @@ public class ArgumentParser {
.defaultHelp(true)
.description("Bitsquare - The decentralized bitcoin exchange");
// Args for seed node config
parser.addArgument("-d", "--" + BOOTSTRAP_NODE_ID_KEY)
.help("Seed node ID");
parser.addArgument("-s", "--" + BOOTSTRAP_NODE_IP_KEY)
.help("Seed node IP");
parser.addArgument("-p", "--" + BOOTSTRAP_NODE_PORT_KEY)
.help("Seed node port");
// Args for local node config
parser.addArgument("--" + Node.NAME_KEY)
.help("Local node name");
parser.addArgument("--" + Node.PORT_KEY)
.help("Local node port");
// Args for bootstrap node config
parser.addArgument("--" + BOOTSTRAP_NODE_NAME_KEY)
.help("Bootstrap node name");
parser.addArgument("--" + BOOTSTRAP_NODE_IP_KEY)
.help("Bootstrap node IP address");
parser.addArgument("--" + BOOTSTRAP_NODE_PORT_KEY)
.help("Bootstrap node port");
// A custom network interface (needed at the moment for windows, but might be useful also later)
parser.addArgument("-i", "--" + NETWORK_INTERFACE_KEY)
parser.addArgument("--" + NETWORK_INTERFACE_KEY)
.help("Network interface");
parser.addArgument("--" + BitcoinModule.BITCOIN_NETWORK_KEY)
.setDefault(BitcoinModule.DEFAULT_BITCOIN_NETWORK.toString())
.help("Bitcoin network to use");
// Args for app config
parser.addArgument("-n", "--" + APP_NAME_KEY)
.help("Name to append to default application name");

View file

@ -0,0 +1,101 @@
/*
* 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.app.cli;
import io.bitsquare.app.ArgumentParser;
import io.bitsquare.network.Node;
import net.tomp2p.dht.PeerBuilderDHT;
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 net.tomp2p.peers.PeerMap;
import net.tomp2p.peers.PeerMapConfiguration;
import net.tomp2p.rpc.ObjectDataReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sourceforge.argparse4j.inf.Namespace;
public class BootstrapNode {
private static final Logger log = LoggerFactory.getLogger(BootstrapNode.class);
private static Peer peer = null;
private static boolean running = true;
public static void main(String[] args) throws Exception {
ArgumentParser parser = new ArgumentParser();
Namespace namespace = parser.parseArgs(args);
String name = namespace.getString(Node.NAME_KEY);
if (name == null)
throw new IllegalArgumentException(String.format("--%s option is required", Node.NAME_KEY));
String portValue = namespace.getString(Node.PORT_KEY);
int port = portValue != null ? Integer.valueOf(portValue) : Node.DEFAULT_PORT;
try {
Number160 peerId = Number160.createHash(name);
PeerMapConfiguration pmc = new PeerMapConfiguration(peerId).peerNoVerification();
PeerMap pm = new PeerMap(pmc);
peer = new PeerBuilder(peerId).ports(port).peerMap(pm).start();
peer.objectDataReply(new ObjectDataReply() {
@Override
public Object reply(PeerAddress sender, Object request) throws Exception {
log.trace("received request: ", request.toString());
return "pong";
}
});
new PeerBuilderDHT(peer).start();
new PeerBuilderNAT(peer).start();
log.debug("started");
new Thread(new Runnable() {
@Override
public void run() {
while (running) {
for (PeerAddress pa : peer.peerBean().peerMap().all()) {
log.debug("peer online:" + pa);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return;
}
}
}
}).start();
} catch (Exception e) {
if (peer != null)
peer.shutdown().awaitUninterruptibly();
}
}
public static void stop() {
running = false;
if (peer != null) {
peer.shutdown().awaitUninterruptibly();
}
peer = null;
}
}

View file

@ -1,169 +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.app.cli;
import io.bitsquare.app.ArgumentParser;
import io.bitsquare.network.BootstrapNodes;
import io.bitsquare.network.Node;
import net.tomp2p.dht.PeerBuilderDHT;
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 net.tomp2p.peers.PeerMap;
import net.tomp2p.peers.PeerMapConfiguration;
import net.tomp2p.rpc.ObjectDataReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sourceforge.argparse4j.inf.Namespace;
import static io.bitsquare.msg.MessageModule.*;
public class SeedNode {
private static final Logger log = LoggerFactory.getLogger(SeedNode.class);
private static Peer peer = null;
private static boolean running = true;
public static void main(String[] args) throws Exception {
ArgumentParser parser = new ArgumentParser();
Namespace namespace = parser.parseArgs(args);
Node defaultNode = BootstrapNodes.DIGITAL_OCEAN_1;
String id = defaultNode.getId();
int port = defaultNode.getPort();
// Passed program args will override the properties of the default bootstrapNode
// So you can use the same id but different ports (e.g. running several nodes on one server with
// different ports)
if (namespace.getString(BOOTSTRAP_NODE_ID_KEY) != null)
id = namespace.getString(BOOTSTRAP_NODE_ID_KEY);
if (namespace.getString(BOOTSTRAP_NODE_PORT_KEY) != null)
port = Integer.valueOf(namespace.getString(BOOTSTRAP_NODE_PORT_KEY));
try {
Number160 peerId = Number160.createHash(id);
PeerMapConfiguration pmc = new PeerMapConfiguration(peerId).peerNoVerification();
PeerMap pm = new PeerMap(pmc);
peer = new PeerBuilder(peerId).ports(port).peerMap(pm).start();
peer.objectDataReply(new ObjectDataReply() {
@Override
public Object reply(PeerAddress sender, Object request) throws Exception {
log.trace("received request: ", request.toString());
return "pong";
}
});
new PeerBuilderDHT(peer).start();
new PeerBuilderNAT(peer).start();
log.debug("SeedNode started.");
new Thread(new Runnable() {
@Override
public void run() {
while (running) {
for (PeerAddress pa : peer.peerBean().peerMap().all()) {
log.debug("peer online:" + pa);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return;
}
}
}
}).start();
} catch (Exception e) {
if (peer != null)
peer.shutdown().awaitUninterruptibly();
}
}
public static void stop() {
running = false;
if (peer != null) {
peer.shutdown().awaitUninterruptibly();
}
peer = null;
}
/*public static void main(String[] args) throws Exception {
ArgumentParser parser = new ArgumentParser();
Namespace namespace = parser.parseArgs(args);
Node defaultNode = BootstrapNodes.DIGITAL_OCEAN_1;
String id = defaultNode.getId();
int port = defaultNode.getPort();
// Passed program args will override the properties of the default bootstrapNode
// So you can use the same id but different ports (e.g. running several nodes on one server with
// different ports)
if (namespace.getString(ArgumentParser.SEED_ID_FLAG) != null)
id = namespace.getString(ArgumentParser.SEED_ID_FLAG);
if (namespace.getString(ArgumentParser.SEED_PORT_FLAG) != null)
port = Integer.valueOf(namespace.getString(ArgumentParser.SEED_PORT_FLAG));
log.info("This node use ID: [" + id + "] and port: [" + port + "]");
Peer peer = null;
try {
// Lets test with different settings
ChannelServerConfiguration csc = PeerBuilder.createDefaultChannelServerConfiguration();
csc.ports(new Ports(Node.DEFAULT_PORT, Node.DEFAULT_PORT));
csc.portsForwarding(new Ports(Node.DEFAULT_PORT, Node.DEFAULT_PORT));
csc.connectionTimeoutTCPMillis(10 * 1000);
csc.idleTCPSeconds(10);
csc.idleUDPSeconds(10);
Bindings bindings = new Bindings();
bindings.addProtocol(StandardProtocolFamily.INET);
peer = new PeerBuilder(Number160.createHash(id)).bindings(bindings)
.channelServerConfiguration(csc).ports(port).start();
peer.objectDataReply((sender, request) -> {
log.trace("received request: ", request.toString());
return "pong";
});
// Needed for DHT support
new PeerBuilderDHT(peer).start();
// Needed for NAT support
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();
}
}*/
}

View file

@ -50,7 +50,9 @@ import lighthouse.files.AppDirectory;
import net.sourceforge.argparse4j.inf.Namespace;
import static io.bitsquare.app.AppModule.APP_NAME_KEY;
import static io.bitsquare.msg.MessageModule.*;
import static io.bitsquare.btc.BitcoinModule.BITCOIN_NETWORK_KEY;
import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*;
import static io.bitsquare.network.Node.*;
public class Main extends Application {
private static final Logger log = LoggerFactory.getLogger(Main.class);
@ -70,8 +72,14 @@ public class Main extends Application {
properties.setProperty(APP_NAME_KEY, appName);
if (argumentsNamespace.getString(BOOTSTRAP_NODE_ID_KEY) != null)
properties.setProperty(BOOTSTRAP_NODE_ID_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_ID_KEY));
if (argumentsNamespace.getString(NAME_KEY) != null)
properties.setProperty(NAME_KEY, argumentsNamespace.getString(NAME_KEY));
if (argumentsNamespace.getString(PORT_KEY) != null)
properties.setProperty(PORT_KEY, argumentsNamespace.getString(PORT_KEY));
if (argumentsNamespace.getString(BOOTSTRAP_NODE_NAME_KEY) != null)
properties.setProperty(BOOTSTRAP_NODE_NAME_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_NAME_KEY));
if (argumentsNamespace.getString(BOOTSTRAP_NODE_IP_KEY) != null)
properties.setProperty(BOOTSTRAP_NODE_IP_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_IP_KEY));
@ -82,6 +90,9 @@ public class Main extends Application {
if (argumentsNamespace.getString(NETWORK_INTERFACE_KEY) != null)
properties.setProperty(NETWORK_INTERFACE_KEY, argumentsNamespace.getString(NETWORK_INTERFACE_KEY));
if (argumentsNamespace.getString(BITCOIN_NETWORK_KEY) != null)
properties.setProperty(BITCOIN_NETWORK_KEY, argumentsNamespace.getString(BITCOIN_NETWORK_KEY));
Application.launch(Main.class, args);
}

View file

@ -30,17 +30,11 @@ import java.util.Properties;
public class BitcoinModule extends BitsquareModule {
private static final BitcoinNetwork DEFAULT_NETWORK = BitcoinNetwork.TESTNET;
private final BitcoinNetwork network;
public static final String BITCOIN_NETWORK_KEY = "bitcoin.network";
public static final String DEFAULT_BITCOIN_NETWORK = BitcoinNetwork.TESTNET.toString();
public BitcoinModule(Properties properties) {
this(properties, DEFAULT_NETWORK);
}
public BitcoinModule(Properties properties, BitcoinNetwork network) {
super(properties);
this.network = network;
}
@Override
@ -57,9 +51,10 @@ public class BitcoinModule extends BitsquareModule {
}
private NetworkParameters network() {
String networkName = properties.getProperty("networkType", network.name());
BitcoinNetwork network = BitcoinNetwork.valueOf(
properties.getProperty(BITCOIN_NETWORK_KEY, DEFAULT_BITCOIN_NETWORK).toUpperCase());
switch (BitcoinNetwork.valueOf(networkName.toUpperCase())) {
switch (network) {
case MAINNET:
return MainNetParams.get();
case TESTNET:
@ -67,7 +62,7 @@ public class BitcoinModule extends BitsquareModule {
case REGTEST:
return RegTestParams.get();
default:
throw new IllegalArgumentException("Unknown bitcoin network name: " + networkName);
throw new IllegalArgumentException("Unknown bitcoin network: " + network);
}
}
}

View file

@ -18,5 +18,5 @@
package io.bitsquare.btc;
public enum BitcoinNetwork {
MAINNET, TESTNET, REGTEST
MAINNET, TESTNET, REGTEST;
}

View file

@ -31,8 +31,6 @@ import io.bitsquare.user.User;
import com.google.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
@ -56,7 +54,6 @@ class MainModel extends UIModel {
private final MessageFacade messageFacade;
private final TradeManager tradeManager;
private final Persistence persistence;
private final int clientPort;
private boolean messageFacadeInited;
private boolean walletFacadeInited;
@ -75,14 +72,12 @@ class MainModel extends UIModel {
@Inject
private MainModel(User user, WalletFacade walletFacade, MessageFacade messageFacade,
TradeManager tradeManager, Persistence persistence,
@Named("clientPort") int clientPort) {
TradeManager tradeManager, Persistence persistence) {
this.user = user;
this.walletFacade = walletFacade;
this.messageFacade = messageFacade;
this.tradeManager = tradeManager;
this.persistence = persistence;
this.clientPort = clientPort;
}
@ -109,10 +104,10 @@ class MainModel extends UIModel {
void initBackend() {
// For testing with the serverside seednode we need the BootstrappedPeerFactory which gets started form
// For testing with the bootstrap node we need the BootstrappedPeerFactory which gets started from
// messageFacade.init
messageFacade.init(clientPort, new BootstrapListener() {
messageFacade.init(new BootstrapListener() {
@Override
public void onCompleted() {
messageFacadeInited = true;

View file

@ -45,7 +45,7 @@ public interface MessageFacade extends MessageBroker {
void getArbitrators(Locale defaultLanguageLocale);
void init(int clientPort, BootstrapListener bootstrapListener);
void init(BootstrapListener bootstrapListener);
void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener);
}

View file

@ -18,22 +18,13 @@
package io.bitsquare.msg;
import io.bitsquare.BitsquareModule;
import io.bitsquare.network.Node;
import com.google.inject.Injector;
import com.google.inject.name.Names;
import java.util.Properties;
import static io.bitsquare.network.BootstrapNodes.DEFAULT_BOOTSTRAP_NODE;
public abstract class MessageModule extends BitsquareModule {
public static final String BOOTSTRAP_NODE_ID_KEY = "id";
public static final String BOOTSTRAP_NODE_IP_KEY = "ip";
public static final String BOOTSTRAP_NODE_PORT_KEY = "port";
public static final String NETWORK_INTERFACE_KEY = "networkInterface";
protected MessageModule(Properties properties) {
super(properties);
}
@ -42,23 +33,6 @@ public abstract class MessageModule extends BitsquareModule {
protected final void configure() {
bind(MessageFacade.class).to(messageFacade()).asEagerSingleton();
// we will probably later use disk storage instead of memory storage for TomP2P
bind(Boolean.class).annotatedWith(Names.named("useDiskStorage")).toInstance(false);
Node bootstrapNode = Node.at(
properties.getProperty(BOOTSTRAP_NODE_ID_KEY, DEFAULT_BOOTSTRAP_NODE.getId()),
properties.getProperty(BOOTSTRAP_NODE_IP_KEY, DEFAULT_BOOTSTRAP_NODE.getIp()),
properties.getProperty(BOOTSTRAP_NODE_PORT_KEY, DEFAULT_BOOTSTRAP_NODE.getPortAsString())
);
bind(Node.class)
.annotatedWith(Names.named("bootstrapNode"))
.toInstance(bootstrapNode);
bind(String.class)
.annotatedWith(Names.named("networkInterface"))
.toInstance(properties.getProperty(NETWORK_INTERFACE_KEY, ""));
doConfigure();
}

View file

@ -68,12 +68,17 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates a DHT peer and bootstrap to the network via a seed node
* Creates a DHT peer and bootstraps to the network via a bootstrap node
*/
class BootstrappedPeerFactory {
private static final Logger log = LoggerFactory.getLogger(BootstrappedPeerFactory.class);
static final String BOOTSTRAP_NODE_KEY = "bootstrapNode";
static final String NETWORK_INTERFACE_KEY = "interface";
static final String NETWORK_INTERFACE_UNSPECIFIED = "<unspecified>";
private KeyPair keyPair;
private Storage storage;
private final Node bootstrapNode;
@ -91,8 +96,9 @@ class BootstrappedPeerFactory {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public BootstrappedPeerFactory(Persistence persistence, @Named("bootstrapNode") Node bootstrapNode,
@Named("networkInterface") String networkInterface) {
public BootstrappedPeerFactory(Persistence persistence,
@Named(BOOTSTRAP_NODE_KEY) Node bootstrapNode,
@Named(NETWORK_INTERFACE_KEY) String networkInterface) {
this.persistence = persistence;
this.bootstrapNode = bootstrapNode;
this.networkInterface = networkInterface;
@ -127,7 +133,7 @@ class BootstrappedPeerFactory {
cc.maxPermitsTCP(100);
cc.maxPermitsUDP(100);
Bindings bindings = new Bindings();
if (!networkInterface.equals(""))
if (!NETWORK_INTERFACE_UNSPECIFIED.equals(networkInterface))
bindings.addInterface(networkInterface);
peer = new PeerBuilder(keyPair).ports(port).peerMap(pm).bindings(bindings)
@ -197,7 +203,7 @@ class BootstrappedPeerFactory {
// 1. Attempt: Try to discover our outside visible address
private void discover() {
setState(BootstrapState.DIRECT_INIT, "We are starting to bootstrap to a seed node.");
setState(BootstrapState.DIRECT_INIT, "We are starting discovery against a bootstrap node.");
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
futureDiscover.addListener(new BaseFutureListener<BaseFuture>() {
@Override
@ -324,7 +330,7 @@ class BootstrappedPeerFactory {
private PeerAddress getBootstrapAddress() {
try {
return new PeerAddress(Number160.createHash(bootstrapNode.getId()),
return new PeerAddress(Number160.createHash(bootstrapNode.getName()),
InetAddress.getByName(bootstrapNode.getIp()),
bootstrapNode.getPort(),
bootstrapNode.getPort());

View file

@ -92,11 +92,10 @@ class TomP2PMessageFacade implements MessageFacade {
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void init(int port, BootstrapListener bootstrapListener) {
public void init(BootstrapListener bootstrapListener) {
p2pNode.setMessageBroker(this);
p2pNode.setKeyPair(user.getMessageKeyPair());
p2pNode.start(port, bootstrapListener);
p2pNode.start(bootstrapListener);
}
public void shutDown() {
@ -219,7 +218,7 @@ class TomP2PMessageFacade implements MessageFacade {
}
}));
// We don't test futureRemove.isSuccess() as this API does not fit well to that operation,
// We don't test futureRemove.isSuccess() as this API does not fit well to that operation,
// it might change in future to something like foundAndRemoved and notFound
// See discussion at: https://github.com/tomp2p/TomP2P/issues/57#issuecomment-62069840

View file

@ -19,18 +19,41 @@ package io.bitsquare.msg.tomp2p;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.MessageModule;
import io.bitsquare.network.BootstrapNodes;
import io.bitsquare.network.Node;
import com.google.inject.name.Names;
import java.util.Properties;
import static io.bitsquare.msg.tomp2p.BootstrappedPeerFactory.*;
public class TomP2PMessageModule extends MessageModule {
public static final String BOOTSTRAP_NODE_NAME_KEY = "bootstrap.node.name";
public static final String BOOTSTRAP_NODE_IP_KEY = "bootstrap.node.ip";
public static final String BOOTSTRAP_NODE_PORT_KEY = "bootstrap.node.port";
public static final String NETWORK_INTERFACE_KEY = BootstrappedPeerFactory.NETWORK_INTERFACE_KEY;
public TomP2PMessageModule(Properties properties) {
super(properties);
}
@Override
protected void doConfigure() {
bind(int.class).annotatedWith(Names.named(Node.PORT_KEY)).toInstance(
Integer.valueOf(properties.getProperty(Node.PORT_KEY, String.valueOf(Node.DEFAULT_PORT))));
bind(TomP2PNode.class).asEagerSingleton();
bind(Node.class).annotatedWith(Names.named(BOOTSTRAP_NODE_KEY)).toInstance(
Node.at(
properties.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.DEFAULT.getName()),
properties.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.DEFAULT.getIp()),
properties.getProperty(BOOTSTRAP_NODE_PORT_KEY, BootstrapNodes.DEFAULT.getPortAsString())
)
);
bindConstant().annotatedWith(Names.named(NETWORK_INTERFACE_KEY)).to(
properties.getProperty(NETWORK_INTERFACE_KEY, NETWORK_INTERFACE_UNSPECIFIED));
bind(BootstrappedPeerFactory.class).asEagerSingleton();
}

View file

@ -19,6 +19,7 @@ package io.bitsquare.msg.tomp2p;
import io.bitsquare.msg.MessageBroker;
import io.bitsquare.msg.listeners.BootstrapListener;
import io.bitsquare.network.Node;
import io.bitsquare.network.tomp2p.TomP2PPeer;
import com.google.common.util.concurrent.FutureCallback;
@ -27,7 +28,6 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.name.Named;
import java.io.File;
import java.io.IOException;
import java.security.KeyPair;
@ -42,13 +42,11 @@ import javax.inject.Inject;
import javafx.application.Platform;
import net.tomp2p.connection.DSASignatureFactory;
import net.tomp2p.connection.PeerConnection;
import net.tomp2p.dht.FutureGet;
import net.tomp2p.dht.FuturePut;
import net.tomp2p.dht.FutureRemove;
import net.tomp2p.dht.PeerDHT;
import net.tomp2p.dht.StorageMemory;
import net.tomp2p.futures.BaseFuture;
import net.tomp2p.futures.BaseFutureListener;
import net.tomp2p.futures.FutureDirect;
@ -57,7 +55,6 @@ import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.storage.Data;
import net.tomp2p.storage.Storage;
import net.tomp2p.storage.StorageDisk;
import net.tomp2p.utils.Utils;
import org.jetbrains.annotations.NotNull;
@ -65,8 +62,6 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lighthouse.files.AppDirectory;
import static io.bitsquare.util.tomp2p.BaseFutureUtil.isSuccess;
/**
@ -79,8 +74,7 @@ public class TomP2PNode {
private static final Logger log = LoggerFactory.getLogger(TomP2PNode.class);
private KeyPair keyPair;
private String appName;
private final Boolean useDiskStorage;
private final int port;
private MessageBroker messageBroker;
private PeerAddress storedPeerAddress;
@ -94,12 +88,9 @@ public class TomP2PNode {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public TomP2PNode(BootstrappedPeerFactory bootstrappedPeerFactory,
@Named("appName") String appName,
@Named("useDiskStorage") Boolean useDiskStorage) {
public TomP2PNode(BootstrappedPeerFactory bootstrappedPeerFactory, @Named(Node.PORT_KEY) int port) {
this.bootstrappedPeerFactory = bootstrappedPeerFactory;
this.appName = appName;
this.useDiskStorage = useDiskStorage;
this.port = port;
}
// for unit testing
@ -109,7 +100,7 @@ public class TomP2PNode {
peerDHT.peerBean().keyPair(keyPair);
messageBroker = (message, peerAddress) -> {
};
useDiskStorage = false;
port = Node.DEFAULT_PORT;
}
@ -126,9 +117,7 @@ public class TomP2PNode {
bootstrappedPeerFactory.setKeyPair(keyPair);
}
public void start(int port, BootstrapListener bootstrapListener) {
useDiscStorage(useDiskStorage);
public void start(BootstrapListener bootstrapListener) {
bootstrappedPeerFactory.setStorage(storage);
setupTimerForIPCheck();
@ -391,19 +380,4 @@ public class TomP2PNode {
log.debug("storePeerAddress " + peerDHT.peerAddress().toString());
return putDomainProtectedData(locationKey, data);
}
private void useDiscStorage(boolean useDiscStorage) {
if (useDiscStorage) {
File path = new File(AppDirectory.dir(appName).toFile() + "/tomP2P");
if (!path.exists()) {
boolean created = path.mkdir();
if (!created)
throw new RuntimeException("Could not create the directory '" + path + "'");
}
storage = new StorageDisk(Number160.ZERO, path, new DSASignatureFactory());
}
else {
storage = new StorageMemory();
}
}
}

View file

@ -20,20 +20,27 @@ package io.bitsquare.network;
import java.util.Arrays;
import java.util.List;
// Ports 7366-7390 are not registered @see
// <a href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=103</a>
// Lets use ports in that range 7366-7390
// 7366 will be used as default 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");
Node DIGITAL_OCEAN_1_DEV = Node.at("digitalocean1.bitsquare.io", "188.226.179.109", 7367);
Node DEFAULT_BOOTSTRAP_NODE = DIGITAL_OCEAN_1;
/**
* Alias to the default bootstrap node.
*/
Node DEFAULT = DIGITAL_OCEAN_1;
/**
* A locally-running {@link io.bitsquare.app.cli.BootstrapNode} instance.
* Typically used only for testing. Not included in results from {@link #all()}.
*/
Node LOCALHOST = Node.at("localhost", "127.0.0.1");
/**
* All known public bootstrap nodes.
*/
static List<Node> all() {
return Arrays.asList(
LOCALHOST, DIGITAL_OCEAN_1
DIGITAL_OCEAN_1
);
}
}

View file

@ -20,32 +20,40 @@ package io.bitsquare.network;
import com.google.common.base.Objects;
public final class Node {
public static final String NAME_KEY = "name";
public static final String PORT_KEY = "port";
/**
* Default port is one <a
* href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=103">
* currently unassigned by IANA</a> (7366-7390).
*/
public static final int DEFAULT_PORT = 7366;
private final String id;
private final String name;
private final String ip;
private final int port;
private Node(String id, String ip, int port) {
this.id = id;
private Node(String name, String ip, int port) {
this.name = name;
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 name, String ip) {
return Node.at(name, ip, DEFAULT_PORT);
}
public static Node at(String id, String ip, int port) {
return new Node(id, ip, port);
public static Node at(String name, String ip, int port) {
return new Node(name, ip, port);
}
public static Node at(String id, String ip, String port) {
return new Node(id, ip, Integer.valueOf(port));
public static Node at(String name, String ip, String port) {
return new Node(name, ip, Integer.valueOf(port));
}
public String getId() {
return id;
public String getName() {
return name;
}
public String getIp() {
@ -60,6 +68,13 @@ public final class Node {
return String.valueOf(port);
}
/**
* Return a copy of this node with the port updated to the given value.
*/
public Node withPort(int newPort) {
return Node.at(this.name, this.ip, newPort);
}
@Override
public boolean equals(Object object) {
if (this == object)
@ -69,20 +84,20 @@ public final class Node {
return false;
Node that = (Node) object;
return Objects.equal(this.id, that.id) &&
return Objects.equal(this.name, that.name) &&
Objects.equal(this.ip, that.ip) &&
Objects.equal(this.port, that.port);
}
@Override
public int hashCode() {
return Objects.hashCode(id, ip, port);
return Objects.hashCode(name, ip, port);
}
@Override
public String toString() {
return Objects.toStringHelper(Node.class.getSimpleName())
.add("id", id)
.add("name", name)
.add("ip", ip)
.add("port", port)
.toString();

View file

@ -1,11 +1 @@
seed.0.id=digitalocean1.bitsquare.io
seed.0.address=188.226.179.109
seed.0.port=5000
seed.1.id=digitalocean2.bitsquare.io
seed.1.address=128.199.251.106
seed.1.port=5000
seed.2.id=localhost
seed.2.address=127.0.0.1
seed.2.port=5001
# Empty for now; see ConfigLoader

View file

@ -1,80 +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 io.bitsquare.network.Node;
import net.tomp2p.connection.Bindings;
import net.tomp2p.connection.ChannelServerConfiguration;
import net.tomp2p.connection.Ports;
import net.tomp2p.connection.StandardProtocolFamily;
import net.tomp2p.dht.PeerBuilderDHT;
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 {
Peer peer = null;
try {
ChannelServerConfiguration csc = PeerBuilder.createDefaultChannelServerConfiguration();
csc.ports(new Ports(Node.DEFAULT_PORT, Node.DEFAULT_PORT));
csc.portsForwarding(new Ports(Node.DEFAULT_PORT, Node.DEFAULT_PORT));
csc.connectionTimeoutTCPMillis(10 * 1000);
csc.idleTCPSeconds(10);
csc.idleUDPSeconds(10);
Bindings bindings = new Bindings();
bindings.addProtocol(StandardProtocolFamily.INET);
peer = new PeerBuilder(Number160.createHash("localhost")).bindings(bindings)
.channelServerConfiguration(csc).ports(Node.DEFAULT_PORT).start();
peer.objectDataReply((sender, request) -> {
log.trace("received request: ", request.toString());
return "pong";
});
// Needed for DHT support
new PeerBuilderDHT(peer).start();
// Needed for NAT support
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();
}
}
}

View file

@ -70,7 +70,7 @@ 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 start a seed node code use the {@link SeedNodeForTesting} class.
* To start a bootstrap node code use the {@link io.bitsquare.app.cli.BootstrapNode} 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.
@ -86,18 +86,17 @@ public class TomP2PTests {
// If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN
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_DEV;
// Typically you run the bootstrap 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 bootstrap node.
private static final Node BOOTSTRAP_NODE = (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) ?
BootstrapNodes.LOCALHOST : BootstrapNodes.DIGITAL_OCEAN_1.withPort(7367);
private static final PeerAddress BOOTSTRAP_NODE_ADDRESS;
static {
try {
BOOTSTRAP_NODE_ADDRESS = new PeerAddress(
Number160.createHash(BOOTSTRAP_NODE.getId()),
Number160.createHash(BOOTSTRAP_NODE.getName()),
BOOTSTRAP_NODE.getIp(), BOOTSTRAP_NODE.getPort(), BOOTSTRAP_NODE.getPort());
} catch (UnknownHostException ex) {
throw new RuntimeException(BOOTSTRAP_NODE.toString(), ex);
@ -252,7 +251,7 @@ public class TomP2PTests {
futureRemove.awaitUninterruptibly();
futureRemove.awaitListenersUninterruptibly();
// We don't test futureRemove.isSuccess() as this API does not fit well to that operation,
// We don't test futureRemove.isSuccess() as this API does not fit well to that operation,
// it might change in future to something like foundAndRemoved and notFound
// See discussion at: https://github.com/tomp2p/TomP2P/issues/57#issuecomment-62069840
@ -305,7 +304,7 @@ public class TomP2PTests {
}
}
// That test should always succeed as we use the server seed node as receiver.
// This test should always succeed as we use the bootstrap node as receiver.
// A node can send a message to another peer which is not in the same LAN.
@Test
@Repeat(STRESS_TEST_COUNT)

View file

@ -38,8 +38,8 @@ public class NodeTests {
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))));
assertThat(node1a, not(equalTo(Node.at(node1a.getName(), "203.0.113.2"))));
assertThat(node1a, not(equalTo(Node.at(node1a.getName(), node1a.getIp(), Node.DEFAULT_PORT + 1))));
Node node2 = Node.at("bitsquare2.example.com", "203.0.113.2");
assertThat(node1a.hashCode(), equalTo(node1b.hashCode()));
@ -57,6 +57,6 @@ public class NodeTests {
@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}"));
assertThat(node.toString(), equalTo("Node{name=bitsquare1.example.com, ip=203.0.113.1, port=5001}"));
}
}

View file

@ -16,99 +16,20 @@
package net.tomp2p.dht;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.Random;
import java.util.TreeSet;
import net.tomp2p.connection.Bindings;
import net.tomp2p.futures.FutureBootstrap;
import net.tomp2p.futures.FutureDiscover;
import net.tomp2p.message.Message;
import net.tomp2p.message.Message.Type;
import net.tomp2p.p2p.AutomaticFuture;
import net.tomp2p.p2p.Peer;
import net.tomp2p.p2p.PeerBuilder;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.peers.PeerMap;
import net.tomp2p.peers.PeerMapConfiguration;
import net.tomp2p.peers.PeerSocketAddress;
public class UtilsDHT2 {
/**
* Used to make the testcases predictable. Used as an input for {@link Random}.
*/
public static final long THE_ANSWER = 42L;
/**
* Having two peers in a network, the seed needs to be different, otherwise we create a peer with the same id twice.
*/
public static final long THE_ANSWER2 = 43L;
public static Message createDummyMessage() throws UnknownHostException {
return createDummyMessage(false, false);
}
public static Message createDummyMessage(boolean firewallUDP, boolean firewallTCP)
throws UnknownHostException {
return createDummyMessage(new Number160("0x4321"), "127.0.0.1", 8001, 8002, new Number160("0x1234"),
"127.0.0.1", 8003, 8004, (byte) 0, Type.REQUEST_1, firewallUDP, firewallTCP);
}
public static PeerAddress createAddress(Number160 id) throws UnknownHostException {
return createAddress(id, "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress() throws UnknownHostException {
return createAddress(new Number160("0x5678"), "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress(int id) throws UnknownHostException {
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress(String id) throws UnknownHostException {
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender,
int udpPortSender, boolean firewallUDP,
boolean firewallTCP) throws UnknownHostException {
InetAddress inetSend = InetAddress.getByName(inetSender);
PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender);
PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false,
PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES);
return n1;
}
public static Message createDummyMessage(Number160 idSender, String inetSender, int tcpPortSendor,
int udpPortSender, Number160 idRecipien, String inetRecipient,
int tcpPortRecipient,
int udpPortRecipient, byte command, Type type, boolean firewallUDP,
boolean firewallTCP)
throws UnknownHostException {
Message message = new Message();
PeerAddress n1 = createAddress(idSender, inetSender, tcpPortSendor, udpPortSender, firewallUDP,
firewallTCP);
message.sender(n1);
//
PeerAddress n2 = createAddress(idRecipien, inetRecipient, tcpPortRecipient, udpPortRecipient,
firewallUDP, firewallTCP);
message.recipient(n2);
message.type(type);
message.command(command);
return message;
}
public static PeerDHT[] createNodes(int nrOfPeers, Random rnd, int port) throws Exception {
return createNodes(nrOfPeers, rnd, port, null);
@ -177,34 +98,6 @@ public class UtilsDHT2 {
return peers;
}
public static Peer[] createRealNodes(int nrOfPeers, Random rnd, int startPort,
AutomaticFuture automaticFuture) throws Exception {
if (nrOfPeers < 1) {
throw new IllegalArgumentException("Cannot create less than 1 peer");
}
Peer[] peers = new Peer[nrOfPeers];
for (int i = 0; i < nrOfPeers; i++) {
peers[i] = new PeerBuilder(new Number160(rnd))
.ports(startPort + i).start().addAutomaticFuture(automaticFuture);
}
System.err.println("real peers created.");
return peers;
}
public static Peer[] createNonMaintenanceNodes(int nrOfPeers, Random rnd, int port) throws IOException {
if (nrOfPeers < 1) {
throw new IllegalArgumentException("Cannot create less than 1 peer");
}
Peer[] peers = new Peer[nrOfPeers];
peers[0] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).ports(port).start();
for (int i = 1; i < nrOfPeers; i++) {
peers[i] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).masterPeer(peers[0])
.start();
}
System.err.println("non-maintenance peers created.");
return peers;
}
/**
* Perfect routing, where each neighbor has contacted each other. This means that for small number of peers, every
* peer knows every other peer.
@ -219,14 +112,6 @@ public class UtilsDHT2 {
System.err.println("perfect routing done.");
}
public static void perfectRoutingIndirect(PeerDHT... peers) {
for (int i = 0; i < peers.length; i++) {
for (int j = 0; j < peers.length; j++)
peers[i].peerBean().peerMap().peerFound(peers[j].peerAddress(), peers[j].peerAddress(), null);
}
System.err.println("perfect routing done.");
}
public static void main(String[] args) throws IOException {
createTempDirectory();
}
@ -246,121 +131,4 @@ public class UtilsDHT2 {
throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS
+ " attempts (tried " + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}
public static Peer[] createAndAttachNodes(int nr, int port, Random rnd) throws Exception {
Peer[] peers = new Peer[nr];
for (int i = 0; i < nr; i++) {
if (i == 0) {
peers[0] = new PeerBuilder(new Number160(rnd)).ports(port).start();
}
else {
peers[i] = new PeerBuilder(new Number160(rnd)).masterPeer(peers[0]).start();
}
}
return peers;
}
public static void bootstrap(Peer[] peers) {
List<FutureBootstrap> futures1 = new ArrayList<FutureBootstrap>();
List<FutureDiscover> futures2 = new ArrayList<FutureDiscover>();
for (int i = 1; i < peers.length; i++) {
FutureDiscover tmp = peers[i].discover().peerAddress(peers[0].peerAddress()).start();
futures2.add(tmp);
}
for (FutureDiscover future : futures2) {
future.awaitUninterruptibly();
}
for (int i = 1; i < peers.length; i++) {
FutureBootstrap tmp = peers[i].bootstrap().peerAddress(peers[0].peerAddress()).start();
futures1.add(tmp);
}
for (int i = 1; i < peers.length; i++) {
FutureBootstrap tmp = peers[0].bootstrap().peerAddress(peers[i].peerAddress()).start();
futures1.add(tmp);
}
for (FutureBootstrap future : futures1)
future.awaitUninterruptibly();
}
public static void routing(Number160 key, Peer[] peers, int start) {
System.out.println("routing: searching for key " + key);
NavigableSet<PeerAddress> pa1 = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
NavigableSet<PeerAddress> queried = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
Number160 result = Number160.ZERO;
Number160 resultPeer = new Number160("0xd75d1a3d57841fbc9e2a3d175d6a35dc2e15b9f");
int round = 0;
while (!resultPeer.equals(result)) {
System.out.println("round " + round);
round++;
pa1.addAll(peers[start].peerBean().peerMap().all());
queried.add(peers[start].peerAddress());
System.out.println("closest so far: " + queried.first());
PeerAddress next = pa1.pollFirst();
while (queried.contains(next)) {
next = pa1.pollFirst();
}
result = next.peerId();
start = findNr(next.peerId().toString(), peers);
}
}
public static void findInMap(PeerAddress key, Peer[] peers) {
for (int i = 0; i < peers.length; i++) {
if (peers[i].peerBean().peerMap().contains(key)) {
System.out.println("Peer " + i + " with the id " + peers[i].peerID() + " knows the peer "
+ key);
}
}
}
public static int findNr(String string, Peer[] peers) {
for (int i = 0; i < peers.length; i++) {
if (peers[i].peerID().equals(new Number160(string))) {
System.out.println("we found the number " + i + " for peer with id " + string);
return i;
}
}
return -1;
}
public static Peer find(String string, Peer[] peers) {
for (int i = 0; i < peers.length; i++) {
if (peers[i].peerID().equals(new Number160(string))) {
System.out.println("!!we found the number " + i + " for peer with id " + string);
return peers[i];
}
}
return null;
}
public static void exec(String cmd) throws Exception {
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
public static PeerAddress createAddressIP(String inet) throws UnknownHostException {
return createAddress(Number160.createHash(inet), inet, 8005, 8006, false, false);
}
public static PeerAddress[] createDummyAddress(int size, int portTCP, int portUDP) throws UnknownHostException {
PeerAddress[] pa = new PeerAddress[size];
for (int i = 0; i < size; i++) {
pa[i] = createAddress(i + 1, portTCP, portUDP);
}
return pa;
}
public static PeerAddress createAddress(int iid, int portTCP, int portUDP) throws UnknownHostException {
Number160 id = new Number160(iid);
InetAddress address = InetAddress.getByName("127.0.0.1");
return new PeerAddress(id, address, portTCP, portUDP);
}
}