Merge branch 'cbeams'

* cbeams:
  Polish FeePolicy
  Use BitcoinNetwork vs. BitcoinJ's NetworkParameters
  Use #ofType in commandline parsing for type safety
  Introduce customized JOptCommandLinePropertySource
  Expose network information to GUI cleanly

Conflicts:
	src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java
This commit is contained in:
Chris Beams 2014-11-13 12:45:34 +01:00
commit f4eeb81390
No known key found for this signature in database
GPG key ID: 3D214F8F5BC5ED73
22 changed files with 320 additions and 296 deletions

View file

@ -22,13 +22,13 @@ import io.bitsquare.btc.UserAgent;
import io.bitsquare.btc.WalletService;
import io.bitsquare.gui.ViewCB;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.util.spring.JOptCommandLinePropertySource;
import java.nio.file.Paths;
import java.util.Properties;
import joptsimple.OptionSet;
import org.springframework.core.env.JOptCommandLinePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
@ -64,7 +64,7 @@ public class BitsquareEnvironment extends StandardEnvironment {
private final String appDataDir;
public BitsquareEnvironment(OptionSet options) {
this(new JOptCommandLinePropertySource(BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME, checkNotNull(options)));
this(new JOptCommandLinePropertySource(BITSQUARE_CLASSPATH_PROPERTY_SOURCE_NAME, checkNotNull(options)));
}
BitsquareEnvironment(PropertySource commandLineProperties) {

View file

@ -32,8 +32,8 @@ public class BootstrapNodeMain extends BitsquareExecutable {
protected void customizeOptionParsing(OptionParser parser) {
parser.accepts(Node.NAME_KEY, "Name of this node").withRequiredArg().isRequired();
parser.accepts(Node.PORT_KEY, "Port to listen on").withRequiredArg()
.defaultsTo(String.valueOf(Node.DEFAULT_PORT));
parser.accepts(Node.PORT_KEY, "Port to listen on").withRequiredArg().ofType(int.class)
.defaultsTo(Node.DEFAULT_PORT);
}
protected void doExecute(OptionSet options) {

View file

@ -19,15 +19,15 @@ package io.bitsquare.app.gui;
import io.bitsquare.app.BitsquareEnvironment;
import io.bitsquare.app.BitsquareExecutable;
import io.bitsquare.btc.BitcoinModule;
import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.network.BootstrapNodes;
import io.bitsquare.network.Node;
import io.bitsquare.util.joptsimple.EnumValueConverter;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import static io.bitsquare.app.BitsquareEnvironment.*;
import static io.bitsquare.btc.BitcoinModule.BITCOIN_NETWORK_KEY;
import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*;
import static io.bitsquare.network.Node.*;
@ -44,11 +44,14 @@ public class BitsquareAppMain extends BitsquareExecutable {
parser.accepts(APP_DATA_DIR_KEY, "Application data directory").withRequiredArg()
.defaultsTo(DEFAULT_APP_DATA_DIR);
parser.accepts(NAME_KEY, "Name of this node").withRequiredArg();
parser.accepts(PORT_KEY, "Port to listen on").withRequiredArg().defaultsTo(String.valueOf(Node.DEFAULT_PORT));
parser.accepts(BITCOIN_NETWORK_KEY).withRequiredArg().defaultsTo(BitcoinModule.DEFAULT_BITCOIN_NETWORK);
parser.accepts(PORT_KEY, "Port to listen on").withRequiredArg().ofType(int.class).defaultsTo(Node.DEFAULT_PORT);
parser.accepts(BitcoinNetwork.KEY).withRequiredArg().ofType(BitcoinNetwork.class)
.withValuesConvertedBy(new EnumValueConverter(BitcoinNetwork.class))
.defaultsTo(BitcoinNetwork.DEFAULT);
parser.accepts(BOOTSTRAP_NODE_NAME_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getName());
parser.accepts(BOOTSTRAP_NODE_IP_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getIp());
parser.accepts(BOOTSTRAP_NODE_PORT_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getPortAsString());
parser.accepts(BOOTSTRAP_NODE_PORT_KEY).withRequiredArg().ofType(int.class)
.defaultsTo(BootstrapNodes.DEFAULT.getPort());
parser.accepts(NETWORK_INTERFACE_KEY, "Network interface").withRequiredArg();
}

View file

@ -34,8 +34,6 @@ import static com.google.inject.name.Names.named;
public class BitcoinModule extends BitsquareModule {
public static final String BITCOIN_NETWORK_KEY = "bitcoin.network";
public static final String DEFAULT_BITCOIN_NETWORK = BitcoinNetwork.TESTNET.toString();
public BitcoinModule(Environment env) {
super(env);
@ -43,7 +41,8 @@ public class BitcoinModule extends BitsquareModule {
@Override
protected void configure() {
bind(NetworkParameters.class).toInstance(network());
bind(BitcoinNetwork.class).toInstance(
env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT));
bind(FeePolicy.class).asEagerSingleton();
bindConstant().annotatedWith(named(UserAgent.NAME_KEY)).to(env.getRequiredProperty(UserAgent.NAME_KEY));
@ -63,21 +62,5 @@ public class BitcoinModule extends BitsquareModule {
protected void doClose(Injector injector) {
injector.getInstance(WalletService.class).shutDown();
}
private NetworkParameters network() {
BitcoinNetwork network = BitcoinNetwork.valueOf(
env.getProperty(BITCOIN_NETWORK_KEY, DEFAULT_BITCOIN_NETWORK).toUpperCase());
switch (network) {
case MAINNET:
return MainNetParams.get();
case TESTNET:
return TestNet3Params.get();
case REGTEST:
return RegTestParams.get();
default:
throw new IllegalArgumentException("Unknown bitcoin network: " + network);
}
}
}

View file

@ -17,6 +17,27 @@
package io.bitsquare.btc;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
public enum BitcoinNetwork {
MAINNET, TESTNET, REGTEST;
MAINNET(MainNetParams.get()),
TESTNET(TestNet3Params.get()),
REGTEST(RegTestParams.get());
public static final String KEY = "bitcoin.network";
public static final BitcoinNetwork DEFAULT = TESTNET;
private final NetworkParameters parameters;
BitcoinNetwork(NetworkParameters parameters) {
this.parameters = parameters;
}
public NetworkParameters getParameters() {
return parameters;
}
}

View file

@ -17,14 +17,12 @@
package io.bitsquare.btc;
import io.bitsquare.BitsquareException;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import javax.inject.Inject;
@ -32,77 +30,60 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FeePolicy {
public static final Coin TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
// The min. REGISTRATION_FEE calculated with Transaction.MIN_NONDUST_OUTPUT would be 0.00015460 which might lead
// to problems for the spending wallet.
// The min. REGISTRATION_FEE calculated with Transaction.MIN_NONDUST_OUTPUT would be
// 0.00015460 which might lead to problems for the spending wallet.
// Some web wallets don't allow more then 4 decimal places (need more investigation)
// So we use 0.0002 as that fits also to our 4 decimal places restriction for BTC values.
// The remaining 0.0000454 BTC is given to miners at the moment as it is lower then dust.
public static final Coin REGISTRATION_FEE = TX_FEE.add(TX_FEE);
public static final Coin CREATE_OFFER_FEE = REGISTRATION_FEE; // 0.0002
public static final Coin TAKE_OFFER_FEE = CREATE_OFFER_FEE;
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
// those are just dummy yet. trading fees will go probably to arbiters
// Not used at the moment
// private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
//
private static String createOfferFeeAddress;
private static String takeOfferFeeAddress;
private final NetworkParameters params;
private final BitcoinNetwork bitcoinNetwork;
private final String createOfferFeeAddress;
private final String takeOfferFeeAddress;
@Inject
public FeePolicy(NetworkParameters params) {
this.params = params;
public FeePolicy(BitcoinNetwork bitcoinNetwork) {
this.bitcoinNetwork = bitcoinNetwork;
if (params.equals(TestNet3Params.get())) {
switch (bitcoinNetwork) {
case TESTNET:
createOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84";
takeOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84";
}
else if (params.equals(MainNetParams.get())) {
break;
case MAINNET:
// bitsquare donation address used for the moment...
createOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7";
takeOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7";
}
else if (params.equals(RegTestParams.get())) {
break;
case REGTEST:
createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
takeOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
break;
default:
throw new BitsquareException("Unknown bitcoin network: %s", bitcoinNetwork);
}
}
//TODO who is receiver? other users or dev address? use donation option list?
// Not used at the moment
// (dev, other users, wikileaks, tor, sub projects (bitcoinj, tomp2p,...)...)
/* public Address getAddressForRegistrationFee() {
try {
return new Address(params, registrationFeeAddress);
} catch (AddressFormatException e) {
e.printStackTrace();
return null;
}
}*/
//TODO get address form arbitrator list
public Address getAddressForCreateOfferFee() {
try {
return new Address(params, createOfferFeeAddress);
} catch (AddressFormatException e) {
e.printStackTrace();
return null;
return new Address(bitcoinNetwork.getParameters(), createOfferFeeAddress);
} catch (AddressFormatException ex) {
throw new BitsquareException(ex);
}
}
//TODO get address form the intersection of both traders arbitrator lists
public Address getAddressForTakeOfferFee() {
try {
return new Address(params, takeOfferFeeAddress);
} catch (AddressFormatException e) {
e.printStackTrace();
return null;
return new Address(bitcoinNetwork.getParameters(), takeOfferFeeAddress);
} catch (AddressFormatException ex) {
throw new BitsquareException(ex);
}
}
}

View file

@ -123,10 +123,10 @@ public class WalletService {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public WalletService(NetworkParameters params, FeePolicy feePolicy, SignatureService signatureService,
public WalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy, SignatureService signatureService,
Persistence persistence, UserAgent userAgent,
@Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix) {
this.params = params;
this.params = bitcoinNetwork.getParameters();
this.feePolicy = feePolicy;
this.signatureService = signatureService;
this.persistence = persistence;

View file

@ -141,6 +141,7 @@ public class PreferencesViewCB extends CachedViewCB {
tab.setContent(view);
((TabPane) root).getSelectionModel().select(tab);
Initializable childController = loader.getController();
if (childController instanceof ViewCB)
((ViewCB) childController).setParent(this);
return childController;

View file

@ -1,136 +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.gui.main.preferences.network;
import io.bitsquare.BitsquareException;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.msg.tomp2p.BootstrappedPeerFactory;
import io.bitsquare.msg.tomp2p.TomP2PNode;
import io.bitsquare.network.BootstrapState;
import io.bitsquare.network.Node;
import org.bitcoinj.core.NetworkParameters;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import net.tomp2p.peers.PeerSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NetworkPreferencesPM extends PresentationModel {
private static final Logger log = LoggerFactory.getLogger(NetworkPreferencesPM.class);
final String bitcoinNetworkType;
final String p2pNetworkConnection;
final String p2pNetworkAddress;
final String bootstrapAddress;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
NetworkPreferencesPM(NetworkParameters networkParameters,
BootstrappedPeerFactory bootstrappedPeerFactory,
TomP2PNode tomP2PNode,
@Named(BootstrappedPeerFactory.BOOTSTRAP_NODE_KEY) Node bootstrapNode) {
switch (networkParameters.getId()) {
case NetworkParameters.ID_REGTEST:
bitcoinNetworkType = "Regtest";
break;
case NetworkParameters.ID_TESTNET:
bitcoinNetworkType = "Testnet";
break;
case NetworkParameters.ID_MAINNET:
bitcoinNetworkType = "Mainnet";
break;
default:
bitcoinNetworkType = "Undefined";
throw new BitsquareException("Invalid networkParameters " + networkParameters.getId());
}
PeerSocketAddress socketAddress = tomP2PNode.getPeerDHT().peerAddress().peerSocketAddress();
p2pNetworkAddress = "IP: " + socketAddress.inetAddress().getHostAddress()
+ ", TCP port: " + socketAddress.tcpPort()
+ ", UDP port: " + socketAddress.udpPort();
bootstrapAddress = "ID: " + bootstrapNode.getName()
+ ", IP: " + bootstrapNode.getIp()
+ ", Port: " + bootstrapNode.getPortAsString();
BootstrapState state = bootstrappedPeerFactory.bootstrapState.get();
if (state == BootstrapState.DIRECT_SUCCESS)
p2pNetworkConnection = "Direct connection";
else if (state == BootstrapState.NAT_SUCCESS)
p2pNetworkConnection = "Connected with automatic port forwarding";
else if (state == BootstrapState.RELAY_SUCCESS)
p2pNetworkConnection = "Relayed by other peers";
else
throw new BitsquareException("Invalid BootstrapState " + state);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize() {
super.initialize();
}
@SuppressWarnings("EmptyMethod")
@Override
public void activate() {
super.activate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -38,7 +38,7 @@
<Insets top="10"/>
</GridPane.margin>
</Label>
<TextField fx:id="bitcoinNetworkType" GridPane.rowIndex="0" GridPane.columnIndex="1"
<TextField fx:id="bitcoinNetwork" GridPane.rowIndex="0" GridPane.columnIndex="1"
mouseTransparent="true" editable="false" focusTraversable="false">
<GridPane.margin>
<Insets top="10"/>
@ -46,11 +46,11 @@
</TextField>
<Label text="P2P network connection:" GridPane.rowIndex="1"/>
<TextField fx:id="p2pNetworkConnection" GridPane.rowIndex="1" GridPane.columnIndex="1"
<TextField fx:id="connectionType" GridPane.rowIndex="1" GridPane.columnIndex="1"
mouseTransparent="true" editable="false" focusTraversable="false"/>
<Label text="My external visible P2P network address:" GridPane.rowIndex="2"/>
<TextField fx:id="p2pNetworkAddress" GridPane.rowIndex="2" GridPane.columnIndex="1"
<TextField fx:id="nodeAddress" GridPane.rowIndex="2" GridPane.columnIndex="1"
mouseTransparent="true" editable="false" focusTraversable="false"/>
<Label text="P2P bootstrap node address:" GridPane.rowIndex="3">
@ -58,7 +58,7 @@
<Insets bottom="-15"/>
</GridPane.margin>
</Label>
<TextField fx:id="bootstrapAddress" GridPane.rowIndex="3" GridPane.columnIndex="1"
<TextField fx:id="bootstrapNodeAddress" GridPane.rowIndex="3" GridPane.columnIndex="1"
mouseTransparent="true" editable="false" focusTraversable="false">
<GridPane.margin>
<Insets bottom="-15"/>

View file

@ -17,7 +17,8 @@
package io.bitsquare.gui.main.preferences.network;
import io.bitsquare.gui.CachedViewCB;
import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.network.ClientNode;
import java.net.URL;
@ -26,62 +27,28 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NetworkPreferencesViewCB implements Initializable {
/**
* This UI is not cached as it is normally only needed once.
*/
public class NetworkPreferencesViewCB extends CachedViewCB<NetworkPreferencesPM> {
private final String bitcoinNetworkValue;
private final ClientNode clientNode;
private static final Logger log = LoggerFactory.getLogger(NetworkPreferencesViewCB.class);
@FXML TextField bitcoinNetworkType, p2pNetworkConnection, p2pNetworkAddress, bootstrapAddress;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@FXML TextField bitcoinNetwork, connectionType, nodeAddress, bootstrapNodeAddress;
@Inject
private NetworkPreferencesViewCB(NetworkPreferencesPM presentationModel) {
super(presentationModel);
public NetworkPreferencesViewCB(BitcoinNetwork bitcoinNetwork, ClientNode clientNode) {
this.bitcoinNetworkValue = bitcoinNetwork.toString();
this.clientNode = clientNode;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("EmptyMethod")
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
bitcoinNetwork.setText(bitcoinNetworkValue);
nodeAddress.setText(clientNode.getAddress().toString());
bootstrapNodeAddress.setText(clientNode.getBootstrapNodeAddress().toString());
connectionType.setText(clientNode.getConnectionType().toString());
}
@Override
public void activate() {
super.activate();
bitcoinNetworkType.setText(presentationModel.bitcoinNetworkType);
p2pNetworkConnection.setText(presentationModel.p2pNetworkConnection);
p2pNetworkAddress.setText(presentationModel.p2pNetworkAddress);
bootstrapAddress.setText(presentationModel.bootstrapAddress);
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
}
@SuppressWarnings("EmptyMethod")
@Override
public void terminate() {
super.terminate();
}
}

View file

@ -17,9 +17,10 @@
package io.bitsquare.gui.util.validation;
import io.bitsquare.btc.BitcoinNetwork;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.NetworkParameters;
import javax.inject.Inject;
@ -33,7 +34,8 @@ import org.slf4j.LoggerFactory;
*/
public final class BtcAddressValidator extends InputValidator {
private static final Logger log = LoggerFactory.getLogger(BtcAddressValidator.class);
private final NetworkParameters networkParameters;
private final BitcoinNetwork bitcoinNetwork;
///////////////////////////////////////////////////////////////////////////////////////////
@ -41,8 +43,8 @@ public final class BtcAddressValidator extends InputValidator {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public BtcAddressValidator(NetworkParameters networkParameters) {
this.networkParameters = networkParameters;
public BtcAddressValidator(BitcoinNetwork bitcoinNetwork) {
this.bitcoinNetwork = bitcoinNetwork;
}
@ -67,7 +69,7 @@ public final class BtcAddressValidator extends InputValidator {
private ValidationResult validateBtcAddress(String input) {
try {
new Address(networkParameters, input);
new Address(bitcoinNetwork.getParameters(), input);
return new ValidationResult(true);
} catch (AddressFormatException e) {
return new ValidationResult(false, "Bitcoin address is a valid format");

View file

@ -70,10 +70,10 @@ import org.slf4j.LoggerFactory;
/**
* Creates a DHT peer and bootstraps to the network via a bootstrap node
*/
public class BootstrappedPeerFactory {
class BootstrappedPeerFactory {
private static final Logger log = LoggerFactory.getLogger(BootstrappedPeerFactory.class);
public static final String BOOTSTRAP_NODE_KEY = "bootstrapNode";
static final String BOOTSTRAP_NODE_KEY = "bootstrapNode";
static final String NETWORK_INTERFACE_KEY = "interface";
static final String NETWORK_INTERFACE_UNSPECIFIED = "<unspecified>";
@ -84,7 +84,8 @@ public class BootstrappedPeerFactory {
private final Persistence persistence;
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
public final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
private final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
private Peer peer;
private PeerDHT peerDHT;
@ -342,6 +343,14 @@ public class BootstrappedPeerFactory {
}
}
public Node getBootstrapNode() {
return bootstrapNode;
}
public ObjectProperty<BootstrapState> getBootstrapState() {
return bootstrapState;
}
private void setState(BootstrapState bootstrapState, String message) {
setState(bootstrapState, message, true);
}

View file

@ -20,10 +20,13 @@ package io.bitsquare.msg.tomp2p;
import io.bitsquare.msg.MessageModule;
import io.bitsquare.msg.MessageService;
import io.bitsquare.network.BootstrapNodes;
import io.bitsquare.network.ClientNode;
import io.bitsquare.network.Node;
import com.google.inject.name.Names;
import javax.inject.Singleton;
import org.springframework.core.env.Environment;
import static io.bitsquare.msg.tomp2p.BootstrappedPeerFactory.*;
@ -43,13 +46,14 @@ public class TomP2PMessageModule extends MessageModule {
protected void doConfigure() {
bind(int.class).annotatedWith(Names.named(Node.PORT_KEY)).toInstance(
env.getProperty(Node.PORT_KEY, Integer.class, Node.DEFAULT_PORT));
bind(TomP2PNode.class).asEagerSingleton();
bind(TomP2PNode.class).in(Singleton.class);
bind(ClientNode.class).to(TomP2PNode.class);
bind(Node.class).annotatedWith(Names.named(BOOTSTRAP_NODE_KEY)).toInstance(
Node.at(
env.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.DEFAULT.getName()),
env.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.DEFAULT.getIp()),
env.getProperty(BOOTSTRAP_NODE_PORT_KEY, BootstrapNodes.DEFAULT.getPortAsString())
env.getProperty(BOOTSTRAP_NODE_PORT_KEY, int.class, BootstrapNodes.DEFAULT.getPort())
)
);
bindConstant().annotatedWith(Names.named(NETWORK_INTERFACE_KEY)).to(

View file

@ -20,6 +20,10 @@ package io.bitsquare.msg.tomp2p;
import io.bitsquare.BitsquareException;
import io.bitsquare.msg.MessageBroker;
import io.bitsquare.msg.listeners.BootstrapListener;
import io.bitsquare.network.BootstrapState;
import io.bitsquare.network.ClientNode;
import io.bitsquare.network.ConnectionType;
import io.bitsquare.network.Node;
import io.bitsquare.network.tomp2p.TomP2PPeer;
import com.google.common.util.concurrent.FutureCallback;
@ -51,6 +55,7 @@ import net.tomp2p.futures.FutureDirect;
import net.tomp2p.futures.FuturePeerConnection;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.peers.PeerSocketAddress;
import net.tomp2p.storage.Data;
import net.tomp2p.utils.Utils;
@ -67,7 +72,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* This class is offering generic functionality of TomP2P needed for Bitsquare, like data and domain protection.
* It does not handle any domain aspects of Bitsquare.
*/
public class TomP2PNode {
public class TomP2PNode implements ClientNode {
private static final Logger log = LoggerFactory.getLogger(TomP2PNode.class);
private KeyPair keyPair;
@ -115,7 +120,7 @@ public class TomP2PNode {
checkNotNull(keyPair, "keyPair must not be null.");
checkNotNull(messageBroker, "messageBroker must not be null.");
bootstrappedPeerFactory.bootstrapState.addListener((ov, oldValue, newValue) ->
bootstrappedPeerFactory.getBootstrapState().addListener((ov, oldValue, newValue) ->
bootstrapListener.onBootstrapStateChanged(newValue));
SettableFuture<PeerDHT> bootstrapFuture = bootstrappedPeerFactory.start();
@ -155,11 +160,6 @@ public class TomP2PNode {
peerDHT.shutdown();
}
public PeerDHT getPeerDHT() {
return peerDHT;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Generic DHT methods
///////////////////////////////////////////////////////////////////////////////////////////
@ -373,4 +373,33 @@ public class TomP2PNode {
log.debug("storePeerAddress " + peerDHT.peerAddress().toString());
return putDomainProtectedData(locationKey, data);
}
@Override
public ConnectionType getConnectionType() {
BootstrapState bootstrapState = bootstrappedPeerFactory.getBootstrapState().get();
switch (bootstrapState) {
case DIRECT_SUCCESS:
return ConnectionType.DIRECT;
case NAT_SUCCESS:
return ConnectionType.NAT;
case RELAY_SUCCESS:
return ConnectionType.RELAY;
default:
throw new BitsquareException("Invalid bootstrap state: %s", bootstrapState);
}
}
@Override
public Node getAddress() {
PeerSocketAddress socketAddress = peerDHT.peerAddress().peerSocketAddress();
return Node.at(
peerDHT.peerID().toString(),
socketAddress.inetAddress().getHostAddress(),
socketAddress.tcpPort());
}
@Override
public Node getBootstrapNodeAddress() {
return bootstrappedPeerFactory.getBootstrapNode();
}
}

View file

@ -0,0 +1,26 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.network;
public interface ClientNode {
ConnectionType getConnectionType();
Node getAddress();
Node getBootstrapNodeAddress();
}

View file

@ -0,0 +1,22 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.network;
public enum ConnectionType {
UNKNOWN, DIRECT, NAT, RELAY
}

View file

@ -64,10 +64,6 @@ public final class Node {
return port;
}
public String getPortAsString() {
return String.valueOf(port);
}
/**
* Return a copy of this node with the port updated to the given value.
*/

View file

@ -0,0 +1,70 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util.joptsimple;
import com.google.common.base.Enums;
import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import java.util.Set;
import joptsimple.ValueConverter;
import static org.springframework.util.StringUtils.collectionToDelimitedString;
/**
* A {@link joptsimple.ValueConverter} that supports case-insensitive conversion from
* String to an enum label. Useful in conjunction with {@link joptsimple.ArgumentAcceptingOptionSpec#ofType(Class)}
* when the type in question is an enum.
*/
public class EnumValueConverter implements ValueConverter<Enum> {
private final Class<? extends Enum> enumType;
public EnumValueConverter(Class<? extends Enum> enumType) {
this.enumType = enumType;
}
/**
* Attempt to resolve an enum of the specified type by looking for a label with the
* given value, trying all case variations in the process.
* @return the matching enum label (if any)
* @throws IllegalArgumentException if no such label matching the given value is found.
*/
@Override
public Enum convert(String value) {
Set<String> candidates = Sets.newHashSet(value, value.toUpperCase(), value.toLowerCase());
for (String candidate : candidates) {
Optional<? extends Enum> result = Enums.getIfPresent(enumType, candidate);
if (result.isPresent())
return result.get();
}
throw new IllegalArgumentException(String.format(
"No enum constant %s.[%s]", enumType.getName(), collectionToDelimitedString(candidates, "|")));
}
@Override
public Class<? extends Enum> valueType() {
return enumType;
}
@Override
public String valuePattern() {
return null;
}
}

View file

@ -0,0 +1,50 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util.spring;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import joptsimple.OptionSet;
/**
* Customizes {@link io.bitsquare.util.spring.JOptCommandLinePropertySource#getOptionValues(String)}
* to allow for proper use of {@link joptsimple.ArgumentAcceptingOptionSpec#ofType(Class)}.
* To be removed once https://github.com/spring-projects/spring-framework/pull/693 has
* been merged and made available in a release.
*/
public class JOptCommandLinePropertySource extends org.springframework.core.env.JOptCommandLinePropertySource {
public JOptCommandLinePropertySource(String name, OptionSet options) {
super(name, options);
}
@Override
public List<String> getOptionValues(String name) {
List<?> argValues = this.source.valuesOf(name);
List<String> stringArgValues = new ArrayList<>();
for (Object argValue : argValues) {
stringArgValues.add(argValue instanceof String ? (String) argValue : argValue.toString());
}
if (stringArgValues.isEmpty()) {
return (this.source.has(name) ? Collections.<String>emptyList() : null);
}
return Collections.unmodifiableList(stringArgValues);
}
}

View file

@ -18,6 +18,7 @@
package io.bitsquare.msg;
import io.bitsquare.network.BootstrapNodes;
import io.bitsquare.network.ConnectionType;
import io.bitsquare.network.Node;
import io.bitsquare.util.Repeat;
import io.bitsquare.util.RepeatRule;
@ -80,10 +81,6 @@ import static org.junit.Assert.*;
public class TomP2PTests {
private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class);
private enum ConnectionType {
UNKNOWN, DIRECT, NAT, RELAY
}
// 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;

View file

@ -46,7 +46,6 @@ public class NodeTests {
assertThat(node1a.hashCode(), not(equalTo(node2.hashCode())));
assertThat(node1a.getPort(), equalTo(Node.DEFAULT_PORT));
assertThat(node1a.getPortAsString(), equalTo(String.valueOf(Node.DEFAULT_PORT)));
Node node3a = Node.at("bitsquare3.example.com", "203.0.113.3", 1234);
Node node3b = Node.at("bitsquare3.example.com", "203.0.113.3", "1234");