diff --git a/src/main/java/io/bitsquare/app/ArgumentParser.java b/src/main/java/io/bitsquare/app/ArgumentParser.java index 61966d389c..bbcc040553 100644 --- a/src/main/java/io/bitsquare/app/ArgumentParser.java +++ b/src/main/java/io/bitsquare/app/ArgumentParser.java @@ -23,9 +23,9 @@ import net.sourceforge.argparse4j.inf.Namespace; public class ArgumentParser { - public static final String PEER_ID_FLAG = "peerid"; - public static final String IP_FLAG = "ip"; - public static final String PORT_FLAG = "port"; + public static final String SEED_ID_FLAG = "id"; + public static final String SEED_IP_FLAG = "ip"; + public static final String SEED_PORT_FLAG = "port"; public static final String INTERFACE_HINT_FLAG = "interface"; public static final String NAME_FLAG = "name"; @@ -35,14 +35,18 @@ public class ArgumentParser { parser = ArgumentParsers.newArgumentParser("Bitsquare") .defaultHelp(true) .description("Bitsquare - The decentralized bitcoin exchange"); - parser.addArgument("-d", "--" + PEER_ID_FLAG) - .help("Seed peer ID"); - parser.addArgument("-d", "--" + IP_FLAG) + + // Args for seed node config + parser.addArgument("-d", "--" + SEED_ID_FLAG) + .help("Seed node ID"); + parser.addArgument("-d", "--" + SEED_IP_FLAG) .help("Seed node IP"); - parser.addArgument("-p", "--" + PORT_FLAG) + parser.addArgument("-p", "--" + SEED_PORT_FLAG) .help("Seed node port"); parser.addArgument("-i", "--" + INTERFACE_HINT_FLAG) .help("Network interface to listen on"); + + // Args for app config parser.addArgument("-n", "--" + NAME_FLAG) .help("Name to append to default application name"); } diff --git a/src/main/java/io/bitsquare/app/cli/SeedNode.java b/src/main/java/io/bitsquare/app/cli/SeedNode.java index 735b986ca6..63c099ffb7 100644 --- a/src/main/java/io/bitsquare/app/cli/SeedNode.java +++ b/src/main/java/io/bitsquare/app/cli/SeedNode.java @@ -18,94 +18,81 @@ package io.bitsquare.app.cli; 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.BootstrapNodes; import io.bitsquare.network.Node; -import java.net.UnknownHostException; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.TimeoutException; - +import net.tomp2p.connection.Bindings; +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; -import akka.actor.ActorRef; -import akka.actor.ActorSystem; -import akka.actor.Inbox; import net.sourceforge.argparse4j.inf.Namespace; -import scala.concurrent.duration.Duration; -import scala.concurrent.duration.FiniteDuration; public class SeedNode { private static final Logger log = LoggerFactory.getLogger(SeedNode.class); - private static String interfaceHint; - - public static void main(String[] args) { + public static void main(String[] args) throws Exception { ArgumentParser parser = new ArgumentParser(); Namespace namespace = parser.parseArgs(args); - if (namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG) != null) - interfaceHint = namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG); + Node defaultNode = BootstrapNodes.DIGITAL_OCEAN_1; + String id = defaultNode.getId(); + int port = defaultNode.getPort(); - int serverPort = Integer.valueOf(namespace.getString(ArgumentParser.PORT_FLAG)); - String seedID = BootstrapNodes.LOCALHOST.getId(); - if (namespace.getString(ArgumentParser.PEER_ID_FLAG) != null) { - seedID = namespace.getString(ArgumentParser.PEER_ID_FLAG); - } + // 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); - final Set peerAddresses = new HashSet<>(); - for (Node node : BootstrapNodes.all()) { - if (!node.getId().equals(seedID)) { - try { - peerAddresses.add(new PeerAddress(Number160.createHash(node.getId()), node.getIp(), - node.getPort(), node.getPort())); - } catch (UnknownHostException uhe) { - log.error("Unknown Host [" + node.getIp() + "]: " + uhe.getMessage()); + 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(); } - - ActorSystem actorSystem = ActorSystem.create("BitsquareSeedNode"); - Inbox inbox = Inbox.create(actorSystem); - ActorRef seedNode = actorSystem.actorOf(DHTManager.getProps(), DHTManager.SEED_NODE); - 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 with ID " + _seedID + - " initialized on port " + ((PeerInitialized) m).getPort()); - } - } catch (Exception e) { - if (!(e instanceof TimeoutException)) { - quit = true; - log.error(e.getMessage()); - } - } - } - actorSystem.shutdown(); - try { - actorSystem.awaitTermination(Duration.create(5L, "seconds")); - } catch (Exception ex) { - if (ex instanceof TimeoutException) - log.error("ActorSystem did not shutdown properly."); - else - log.error(ex.getMessage()); - } - }); - seedNodeThread.start(); } } diff --git a/src/main/java/io/bitsquare/app/cli/SeedNodeUsingAkka.java b/src/main/java/io/bitsquare/app/cli/SeedNodeUsingAkka.java new file mode 100644 index 0000000000..881ecd6a9b --- /dev/null +++ b/src/main/java/io/bitsquare/app/cli/SeedNodeUsingAkka.java @@ -0,0 +1,111 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.app.cli; + +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.BootstrapNodes; +import io.bitsquare.network.Node; + +import java.net.UnknownHostException; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeoutException; + +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Inbox; +import net.sourceforge.argparse4j.inf.Namespace; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; + +public class SeedNodeUsingAkka { + private static final Logger log = LoggerFactory.getLogger(SeedNodeUsingAkka.class); + + private static String interfaceHint; + + public static void main(String[] args) { + ArgumentParser parser = new ArgumentParser(); + Namespace namespace = parser.parseArgs(args); + + if (namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG) != null) + interfaceHint = namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG); + + int serverPort = Integer.valueOf(namespace.getString(ArgumentParser.SEED_PORT_FLAG)); + String seedID = BootstrapNodes.LOCALHOST.getId(); + if (namespace.getString(ArgumentParser.SEED_ID_FLAG) != null) { + seedID = namespace.getString(ArgumentParser.SEED_ID_FLAG); + } + + final Set peerAddresses = new HashSet<>(); + for (Node node : BootstrapNodes.all()) { + if (!node.getId().equals(seedID)) { + try { + peerAddresses.add(new PeerAddress(Number160.createHash(node.getId()), node.getIp(), + node.getPort(), node.getPort())); + } catch (UnknownHostException uhe) { + log.error("Unknown Host [" + node.getIp() + "]: " + uhe.getMessage()); + } + } + } + + ActorSystem actorSystem = ActorSystem.create("BitsquareSeedNode"); + Inbox inbox = Inbox.create(actorSystem); + ActorRef seedNode = actorSystem.actorOf(DHTManager.getProps(), DHTManager.SEED_NODE); + 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 with ID " + _seedID + + " initialized on port " + ((PeerInitialized) m).getPort()); + } + } catch (Exception e) { + if (!(e instanceof TimeoutException)) { + quit = true; + log.error(e.getMessage()); + } + } + } + actorSystem.shutdown(); + try { + actorSystem.awaitTermination(Duration.create(5L, "seconds")); + } catch (Exception ex) { + if (ex instanceof TimeoutException) + log.error("ActorSystem did not shutdown properly."); + else + log.error(ex.getMessage()); + } + }); + seedNodeThread.start(); + } +} diff --git a/src/main/java/io/bitsquare/msg/MessageModule.java b/src/main/java/io/bitsquare/msg/MessageModule.java index 534ebe0a78..d371eddb20 100644 --- a/src/main/java/io/bitsquare/msg/MessageModule.java +++ b/src/main/java/io/bitsquare/msg/MessageModule.java @@ -51,14 +51,14 @@ public abstract class MessageModule extends BitsquareModule { // Passed program args will override the properties of the default bootstrapNode // So you can use the same id and ip but different ports (e.g. running several nodes on one server with // different ports) - if (argumentsNamespace.getString(ArgumentParser.PEER_ID_FLAG) != null) - bootstrapNode.setId(argumentsNamespace.getString(ArgumentParser.PEER_ID_FLAG)); + if (argumentsNamespace.getString(ArgumentParser.SEED_ID_FLAG) != null) + bootstrapNode.setId(argumentsNamespace.getString(ArgumentParser.SEED_ID_FLAG)); - if (argumentsNamespace.getString(ArgumentParser.IP_FLAG) != null) - bootstrapNode.setIp(argumentsNamespace.getString(ArgumentParser.IP_FLAG)); + if (argumentsNamespace.getString(ArgumentParser.SEED_IP_FLAG) != null) + bootstrapNode.setIp(argumentsNamespace.getString(ArgumentParser.SEED_IP_FLAG)); - if (argumentsNamespace.getString(ArgumentParser.PORT_FLAG) != null) - bootstrapNode.setPort(Integer.valueOf(argumentsNamespace.getString(ArgumentParser.PORT_FLAG))); + if (argumentsNamespace.getString(ArgumentParser.SEED_PORT_FLAG) != null) + bootstrapNode.setPort(Integer.valueOf(argumentsNamespace.getString(ArgumentParser.SEED_PORT_FLAG))); bind(Node.class) .annotatedWith(Names.named("bootstrapNode"))