mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-26 00:15:18 -04:00
added jars, fixed tests
This commit is contained in:
parent
3711519e3a
commit
c5ee2c9186
36 changed files with 341 additions and 258 deletions
|
@ -17,15 +17,10 @@
|
||||||
|
|
||||||
package io.bitsquare.common.crypto;
|
package io.bitsquare.common.crypto;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
public final class DecryptedPayloadWithPubKey implements Serializable {
|
public final class DecryptedPayloadWithPubKey implements Serializable {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
|
||||||
|
|
||||||
public final Serializable payload;
|
public final Serializable payload;
|
||||||
public final PublicKey sigPublicKey;
|
public final PublicKey sigPublicKey;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ public class Encryption {
|
||||||
return cipher.doFinal(encryptedPayload);
|
return cipher.doFinal(encryptedPayload);
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
|
||||||
| BadPaddingException | IllegalBlockSizeException | NoSuchProviderException e) {
|
| BadPaddingException | IllegalBlockSizeException | NoSuchProviderException e) {
|
||||||
e.printStackTrace();
|
|
||||||
throw new CryptoException(e);
|
throw new CryptoException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.security.interfaces.DSAPrivateKey;
|
||||||
import java.security.interfaces.RSAPrivateCrtKey;
|
import java.security.interfaces.RSAPrivateCrtKey;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
|
||||||
// TODO: use a password protection for storage?
|
// TODO: use a password protection for key storage
|
||||||
public class KeyStorage {
|
public class KeyStorage {
|
||||||
private static final Logger log = LoggerFactory.getLogger(KeyStorage.class);
|
private static final Logger log = LoggerFactory.getLogger(KeyStorage.class);
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ public class KeyStorage {
|
||||||
if (!storageDir.exists())
|
if (!storageDir.exists())
|
||||||
storageDir.mkdir();
|
storageDir.mkdir();
|
||||||
|
|
||||||
|
|
||||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
|
||||||
try (FileOutputStream fos = new FileOutputStream(storageDir + "/" + name + ".key")) {
|
try (FileOutputStream fos = new FileOutputStream(storageDir + "/" + name + ".key")) {
|
||||||
fos.write(pkcs8EncodedKeySpec.getEncoded());
|
fos.write(pkcs8EncodedKeySpec.getEncoded());
|
||||||
|
|
23
core/pom.xml
23
core/pom.xml
|
@ -49,29 +49,6 @@
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.msopentech.thali</groupId>
|
|
||||||
<artifactId>universal</artifactId>
|
|
||||||
<version>0.0.3-SNAPSHOT</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.msopentech.thali</groupId>
|
|
||||||
<artifactId>java</artifactId>
|
|
||||||
<version>0.0.3-SNAPSHOT</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bitcoinj</groupId>
|
<groupId>org.bitcoinj</groupId>
|
||||||
<artifactId>bitcoinj-core</artifactId>
|
<artifactId>bitcoinj-core</artifactId>
|
||||||
|
|
|
@ -173,18 +173,12 @@ public class ArbitratorManager {
|
||||||
.collect(Collectors.toMap(Arbitrator::getArbitratorAddress, Function.identity()));
|
.collect(Collectors.toMap(Arbitrator::getArbitratorAddress, Function.identity()));
|
||||||
|
|
||||||
arbitratorsObservableMap.putAll(filtered);
|
arbitratorsObservableMap.putAll(filtered);
|
||||||
|
|
||||||
log.debug("filtered arbitrators: " + arbitratorsObservableMap.values());
|
|
||||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
|
||||||
|
|
||||||
// we need to remove accepted arbitrators which are not available anymore
|
// we need to remove accepted arbitrators which are not available anymore
|
||||||
if (user.getAcceptedArbitrators() != null) {
|
if (user.getAcceptedArbitrators() != null) {
|
||||||
List<Arbitrator> removeList = user.getAcceptedArbitrators().stream()
|
List<Arbitrator> removeList = user.getAcceptedArbitrators().stream()
|
||||||
.filter(e -> !arbitratorsObservableMap.containsValue(e))
|
.filter(e -> !arbitratorsObservableMap.containsValue(e))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
removeList.stream().forEach(user::removeAcceptedArbitrator);
|
removeList.stream().forEach(user::removeAcceptedArbitrator);
|
||||||
log.trace("removeList arbitrators: " + removeList.toString());
|
|
||||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
|
||||||
|
|
||||||
// if we don't have any arbitrator anymore we set all matching
|
// if we don't have any arbitrator anymore we set all matching
|
||||||
if (user.getAcceptedArbitrators().isEmpty()) {
|
if (user.getAcceptedArbitrators().isEmpty()) {
|
||||||
|
@ -192,8 +186,6 @@ public class ArbitratorManager {
|
||||||
.filter(arbitrator -> user.hasMatchingLanguage(arbitrator))
|
.filter(arbitrator -> user.hasMatchingLanguage(arbitrator))
|
||||||
.forEach(arbitrator -> user.addAcceptedArbitrator(arbitrator));
|
.forEach(arbitrator -> user.addAcceptedArbitrator(arbitrator));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,8 @@ public class DisputeManager {
|
||||||
log.debug("decryptedMessageWithPubKey.message " + message);
|
log.debug("decryptedMessageWithPubKey.message " + message);
|
||||||
if (message instanceof DisputeMessage) {
|
if (message instanceof DisputeMessage) {
|
||||||
dispatchMessage((DisputeMessage) message);
|
dispatchMessage((DisputeMessage) message);
|
||||||
p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
|
//TODO
|
||||||
|
//p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
decryptedMailboxMessageWithPubKeys.clear();
|
decryptedMailboxMessageWithPubKeys.clear();
|
||||||
|
|
|
@ -987,7 +987,7 @@ public class TradeWalletService {
|
||||||
|
|
||||||
private void verifyTransaction(Transaction transaction) throws TransactionVerificationException {
|
private void verifyTransaction(Transaction transaction) throws TransactionVerificationException {
|
||||||
try {
|
try {
|
||||||
log.trace("Verify transaction");
|
log.trace("Verify transaction " + transaction);
|
||||||
transaction.verify();
|
transaction.verify();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
|
|
|
@ -205,6 +205,7 @@ public class TradeManager {
|
||||||
// after we are authenticated we remove mailbox messages.
|
// after we are authenticated we remove mailbox messages.
|
||||||
DecryptedMsgWithPubKey mailboxMessage = trade.getMailboxMessage();
|
DecryptedMsgWithPubKey mailboxMessage = trade.getMailboxMessage();
|
||||||
if (mailboxMessage != null) {
|
if (mailboxMessage != null) {
|
||||||
|
log.trace("initPendingTrades/removeEntryFromMailbox mailboxMessage = " + mailboxMessage);
|
||||||
p2PService.removeEntryFromMailbox(mailboxMessage);
|
p2PService.removeEntryFromMailbox(mailboxMessage);
|
||||||
trade.setMailboxMessage(null);
|
trade.setMailboxMessage(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,6 @@ public class DisputesView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||||
boolean isArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream()
|
boolean isArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream()
|
||||||
.filter(e -> e.getPubKeyRing() != null && e.getPubKeyRing().equals(keyRing.getPubKeyRing()))
|
.filter(e -> e.getPubKeyRing() != null && e.getPubKeyRing().equals(keyRing.getPubKeyRing()))
|
||||||
.findAny().isPresent();
|
.findAny().isPresent();
|
||||||
log.debug("arbitratorManager.getArbitratorsObservableMap() " + arbitratorManager.getArbitratorsObservableMap().size());
|
|
||||||
log.debug("updateArbitratorsDisputesTabDisableState isArbitrator=" + isArbitrator);
|
|
||||||
arbitratorsDisputesTab.setDisable(!isArbitrator);
|
arbitratorsDisputesTab.setDisable(!isArbitrator);
|
||||||
if (arbitratorsDisputesTab.getContent() != null)
|
if (arbitratorsDisputesTab.getContent() != null)
|
||||||
arbitratorsDisputesTab.getContent().setDisable(!isArbitrator);
|
arbitratorsDisputesTab.getContent().setDisable(!isArbitrator);
|
||||||
|
|
|
@ -68,7 +68,6 @@ class MarketViewModel extends ActivatableViewModel {
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
offerBookListItems.addListener(listChangeListener);
|
offerBookListItems.addListener(listChangeListener);
|
||||||
offerBook.fillOfferBookListItems();
|
offerBook.fillOfferBookListItems();
|
||||||
//updateChartData(offerBookListItems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -122,8 +122,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
||||||
this.tradeCurrency = tradeCurrency;
|
this.tradeCurrency = tradeCurrency;
|
||||||
tradeCurrencyCode.set(tradeCurrency.getCode());
|
tradeCurrencyCode.set(tradeCurrency.getCode());
|
||||||
/* if (!(tradeCurrency instanceof AllTradeCurrenciesEntry))*/
|
filterList();
|
||||||
//offerBook.getOffers(tradeCurrencyCode.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSetPaymentMethod(PaymentMethod paymentMethod) {
|
public void onSetPaymentMethod(PaymentMethod paymentMethod) {
|
||||||
|
@ -273,11 +272,12 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
filteredItems.setPredicate(offerBookListItem -> {
|
filteredItems.setPredicate(offerBookListItem -> {
|
||||||
Offer offer = offerBookListItem.getOffer();
|
Offer offer = offerBookListItem.getOffer();
|
||||||
boolean directionResult = offer.getDirection() != direction;
|
boolean directionResult = offer.getDirection() != direction;
|
||||||
|
boolean currencyResult = offer.getCurrencyCode().equals(tradeCurrency.getCode());
|
||||||
boolean paymentMethodResult = true;
|
boolean paymentMethodResult = true;
|
||||||
if (!(paymentMethod instanceof AllPaymentMethodsEntry))
|
if (!(paymentMethod instanceof AllPaymentMethodsEntry))
|
||||||
paymentMethodResult = offer.getPaymentMethod().equals(paymentMethod);
|
paymentMethodResult = offer.getPaymentMethod().equals(paymentMethod);
|
||||||
|
|
||||||
return directionResult && paymentMethodResult;
|
return directionResult && currencyResult && paymentMethodResult;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
network/libs/java-0.0.3-SNAPSHOT.jar
Normal file
BIN
network/libs/java-0.0.3-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
network/libs/universal-0.0.3-SNAPSHOT.jar
Normal file
BIN
network/libs/universal-0.0.3-SNAPSHOT.jar
Normal file
Binary file not shown.
|
@ -22,6 +22,8 @@
|
||||||
<groupId>com.msopentech.thali</groupId>
|
<groupId>com.msopentech.thali</groupId>
|
||||||
<artifactId>universal</artifactId>
|
<artifactId>universal</artifactId>
|
||||||
<version>0.0.3-SNAPSHOT</version>
|
<version>0.0.3-SNAPSHOT</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${basedir}/libs/universal-0.0.3-SNAPSHOT.jar</systemPath>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
@ -33,6 +35,8 @@
|
||||||
<groupId>com.msopentech.thali</groupId>
|
<groupId>com.msopentech.thali</groupId>
|
||||||
<artifactId>java</artifactId>
|
<artifactId>java</artifactId>
|
||||||
<version>0.0.3-SNAPSHOT</version>
|
<version>0.0.3-SNAPSHOT</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${basedir}/libs/java-0.0.3-SNAPSHOT.jar</systemPath>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package io.bitsquare.crypto;
|
package io.bitsquare.crypto;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.common.crypto.SealedAndSigned;
|
import io.bitsquare.common.crypto.SealedAndSigned;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.messaging.MailboxMessage;
|
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||||
|
|
||||||
public class SealedAndSignedMessage implements MailboxMessage {
|
public final class SealedAndSignedMessage implements MailboxMessage {
|
||||||
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final SealedAndSigned sealedAndSigned;
|
public final SealedAndSigned sealedAndSigned;
|
||||||
public final Address peerAddress;
|
public final Address peerAddress;
|
||||||
|
|
||||||
|
|
|
@ -141,24 +141,24 @@ public class P2PService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPeerAddressAuthenticated(Address peerAddress, Connection connection) {
|
public void onPeerAddressAuthenticated(Address peerAddress, Connection connection) {
|
||||||
|
checkArgument(peerAddress.equals(connection.getPeerAddress()));
|
||||||
authenticatedPeerAddresses.add(peerAddress);
|
authenticatedPeerAddresses.add(peerAddress);
|
||||||
|
|
||||||
if (!authenticatedToFirstPeer) {
|
if (!authenticatedToFirstPeer) {
|
||||||
authenticatedToFirstPeer = true;
|
authenticatedToFirstPeer = true;
|
||||||
|
|
||||||
Address address = connection.getPeerAddress();
|
SettableFuture<Connection> future = sendMessage(peerAddress,
|
||||||
SettableFuture<Connection> future = sendMessage(address,
|
|
||||||
new GetDataSetMessage(addToListAndGetNonce()));
|
new GetDataSetMessage(addToListAndGetNonce()));
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@Nullable Connection connection) {
|
public void onSuccess(@Nullable Connection connection) {
|
||||||
log.info("onPeerAddressAuthenticated Send GetAllDataMessage to " + address + " succeeded.");
|
log.info("onPeerAddressAuthenticated Send GetAllDataMessage to " + peerAddress + " succeeded.");
|
||||||
connectedSeedNodes.add(address);
|
connectedSeedNodes.add(peerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable throwable) {
|
public void onFailure(Throwable throwable) {
|
||||||
log.warn("onPeerAddressAuthenticated Send GetAllDataMessage to " + address + " failed. " +
|
log.warn("onPeerAddressAuthenticated Send GetAllDataMessage to " + peerAddress + " failed. " +
|
||||||
"Exception:" + throwable.getMessage());
|
"Exception:" + throwable.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -171,9 +171,8 @@ public class P2PService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
Address peerAddress = connection.getPeerAddress();
|
if (connection.isAuthenticated())
|
||||||
if (peerAddress != null)
|
authenticatedPeerAddresses.remove(connection.getPeerAddress());
|
||||||
authenticatedPeerAddresses.remove(peerAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -195,11 +194,15 @@ public class P2PService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (message instanceof DataSetMessage) {
|
} else if (message instanceof DataSetMessage) {
|
||||||
log.trace("Received AllDataMessage: " + message);
|
DataSetMessage dataSetMessage = (DataSetMessage) message;
|
||||||
|
StringBuilder sb = new StringBuilder("Received DataSetMessage:\n\n");
|
||||||
|
dataSetMessage.set.stream().forEach(e -> sb.append(e.toString() + "\n"));
|
||||||
|
sb.append("\n");
|
||||||
|
log.trace(sb.toString());
|
||||||
// we keep that connection open as the bootstrapping peer will use that for the authentication
|
// we keep that connection open as the bootstrapping peer will use that for the authentication
|
||||||
|
|
||||||
// as we are not authenticated yet the data adding will not be broadcasted
|
// as we are not authenticated yet the data adding will not be broadcasted
|
||||||
HashSet<ProtectedData> set = ((DataSetMessage) message).set;
|
HashSet<ProtectedData> set = dataSetMessage.set;
|
||||||
set.stream().forEach(e -> dataStorage.add(e, connection.getPeerAddress()));
|
set.stream().forEach(e -> dataStorage.add(e, connection.getPeerAddress()));
|
||||||
|
|
||||||
dataReceived();
|
dataReceived();
|
||||||
|
@ -664,7 +667,7 @@ public class P2PService {
|
||||||
e -> e.onMailboxMessageAdded(decryptedMsgWithPubKey, senderAddress)));
|
e -> e.onMailboxMessageAdded(decryptedMsgWithPubKey, senderAddress)));
|
||||||
}
|
}
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
log.trace("Decryption of SealedAndSignedMessage failed. That is expected if the message is not intended for us.");
|
log.trace("Decryption of SealedAndSignedMessage failed. That is expected if the message is not intended for us. " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class Connection {
|
||||||
|
|
||||||
lastActivityDate = new Date();
|
lastActivityDate = new Date();
|
||||||
|
|
||||||
|
log.trace("\nNew connection created " + this.toString());
|
||||||
connectionListener.onConnection(this);
|
connectionListener.onConnection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,10 +149,6 @@ public class Connection {
|
||||||
// Getters
|
// Getters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Socket getSocket() {
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Address getPeerAddress() {
|
public Address getPeerAddress() {
|
||||||
return peerAddress;
|
return peerAddress;
|
||||||
|
@ -170,14 +167,6 @@ public class Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void setPeerAddress(Address peerAddress) {
|
|
||||||
this.peerAddress = peerAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ShutDown
|
// ShutDown
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -198,6 +187,7 @@ public class Connection {
|
||||||
if (!shutDownInProgress) {
|
if (!shutDownInProgress) {
|
||||||
log.info("\n\nShutDown connection:"
|
log.info("\n\nShutDown connection:"
|
||||||
+ "\npeerAddress=" + peerAddress
|
+ "\npeerAddress=" + peerAddress
|
||||||
|
+ "\nobjectId=" + getObjectId()
|
||||||
+ "\nuid=" + getUid()
|
+ "\nuid=" + getUid()
|
||||||
+ "\nisAuthenticated=" + isAuthenticated
|
+ "\nisAuthenticated=" + isAuthenticated
|
||||||
+ "\nsocket.getPort()=" + socket.getPort()
|
+ "\nsocket.getPort()=" + socket.getPort()
|
||||||
|
@ -205,9 +195,12 @@ public class Connection {
|
||||||
log.debug("ShutDown " + this.getObjectId());
|
log.debug("ShutDown " + this.getObjectId());
|
||||||
log.debug("ShutDown connection requested. Connection=" + this.toString());
|
log.debug("ShutDown connection requested. Connection=" + this.toString());
|
||||||
|
|
||||||
|
if (!stopped) {
|
||||||
|
stopped = true;
|
||||||
shutDownInProgress = true;
|
shutDownInProgress = true;
|
||||||
inputHandlerStopped = true;
|
inputHandlerStopped = true;
|
||||||
if (!stopped) {
|
connectionListener.onDisconnect(ConnectionListener.Reason.SHUT_DOWN, Connection.this);
|
||||||
|
|
||||||
if (sendCloseConnectionMessage) {
|
if (sendCloseConnectionMessage) {
|
||||||
sendMessage(new CloseConnectionMessage());
|
sendMessage(new CloseConnectionMessage());
|
||||||
try {
|
try {
|
||||||
|
@ -217,8 +210,6 @@ public class Connection {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stopped = true;
|
|
||||||
connectionListener.onDisconnect(ConnectionListener.Reason.SHUT_DOWN, Connection.this);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
|
@ -282,7 +273,7 @@ public class Connection {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Connection{" +
|
return "Connection{" +
|
||||||
"OBJECT ID=" + super.toString().split("@")[1] +
|
"objectId=" + getObjectId() +
|
||||||
", uid=" + uid +
|
", uid=" + uid +
|
||||||
", port=" + port +
|
", port=" + port +
|
||||||
", isAuthenticated=" + isAuthenticated +
|
", isAuthenticated=" + isAuthenticated +
|
||||||
|
@ -310,7 +301,7 @@ public class Connection {
|
||||||
try {
|
try {
|
||||||
log.trace("InputHandler waiting for incoming messages connection=" + Connection.this.getObjectId());
|
log.trace("InputHandler waiting for incoming messages connection=" + Connection.this.getObjectId());
|
||||||
Object rawInputObject = in.readObject();
|
Object rawInputObject = in.readObject();
|
||||||
log.trace("New data arrived at inputHandler of connection=" + Connection.this.getObjectId()
|
log.trace("New data arrived at inputHandler of connection=" + Connection.this.toString()
|
||||||
+ " rawInputObject " + rawInputObject);
|
+ " rawInputObject " + rawInputObject);
|
||||||
|
|
||||||
int size = ByteArrayUtils.objectToByteArray(rawInputObject).length;
|
int size = ByteArrayUtils.objectToByteArray(rawInputObject).length;
|
||||||
|
@ -339,10 +330,12 @@ public class Connection {
|
||||||
if (serializable instanceof Message) {
|
if (serializable instanceof Message) {
|
||||||
lastActivityDate = new Date();
|
lastActivityDate = new Date();
|
||||||
Message message = (Message) serializable;
|
Message message = (Message) serializable;
|
||||||
if (message instanceof CloseConnectionMessage)
|
if (message instanceof CloseConnectionMessage) {
|
||||||
|
inputHandlerStopped = true;
|
||||||
shutDown(false);
|
shutDown(false);
|
||||||
else
|
} else {
|
||||||
executorService.submit(() -> messageListener.onMessage(message, Connection.this));
|
executorService.submit(() -> messageListener.onMessage(message, Connection.this));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reportIllegalRequest(IllegalRequest.InvalidDataType);
|
reportIllegalRequest(IllegalRequest.InvalidDataType);
|
||||||
}
|
}
|
||||||
|
@ -355,6 +348,9 @@ public class Connection {
|
||||||
reportIllegalRequest(IllegalRequest.MaxSizeExceeded);
|
reportIllegalRequest(IllegalRequest.MaxSizeExceeded);
|
||||||
}
|
}
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
log.error("Exception at Connection.InputHandler. Connection=" + Connection.this.toString());
|
||||||
|
log.error("Exception=" + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
inputHandlerStopped = true;
|
inputHandlerStopped = true;
|
||||||
handleConnectionException(e);
|
handleConnectionException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ import java.util.function.Consumer;
|
||||||
public class LocalhostNetworkNode extends NetworkNode {
|
public class LocalhostNetworkNode extends NetworkNode {
|
||||||
private static final Logger log = LoggerFactory.getLogger(LocalhostNetworkNode.class);
|
private static final Logger log = LoggerFactory.getLogger(LocalhostNetworkNode.class);
|
||||||
|
|
||||||
private static int simulateTorDelayTorNode = 0;
|
private static int simulateTorDelayTorNode = 2 * 1000;
|
||||||
private static int simulateTorDelayHiddenService = 0;
|
private static int simulateTorDelayHiddenService = 2 * 1000;
|
||||||
private Address address;
|
private Address address;
|
||||||
|
|
||||||
public static void setSimulateTorDelayTorNode(int simulateTorDelayTorNode) {
|
public static void setSimulateTorDelayTorNode(int simulateTorDelayTorNode) {
|
||||||
|
@ -94,7 +94,10 @@ public class LocalhostNetworkNode extends NetworkNode {
|
||||||
long ts = System.currentTimeMillis();
|
long ts = System.currentTimeMillis();
|
||||||
log.trace("[simulation] Create TorNode");
|
log.trace("[simulation] Create TorNode");
|
||||||
if (simulateTorDelayTorNode > 0) Thread.sleep(simulateTorDelayTorNode);
|
if (simulateTorDelayTorNode > 0) Thread.sleep(simulateTorDelayTorNode);
|
||||||
log.trace("\n\n##### TorNode created [simulation]. Took " + (System.currentTimeMillis() - ts) + " ms\n\n");
|
log.info("\n\n############################################################\n" +
|
||||||
|
"TorNode created [simulation]:" +
|
||||||
|
"\nTook " + (System.currentTimeMillis() - ts) + " ms"
|
||||||
|
+ "\n############################################################\n");
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
ListenableFuture<TorNode<JavaOnionProxyManager, JavaOnionProxyContext>> future = executorService.submit(task);
|
ListenableFuture<TorNode<JavaOnionProxyManager, JavaOnionProxyContext>> future = executorService.submit(task);
|
||||||
|
@ -114,7 +117,10 @@ public class LocalhostNetworkNode extends NetworkNode {
|
||||||
long ts = System.currentTimeMillis();
|
long ts = System.currentTimeMillis();
|
||||||
log.debug("[simulation] Create hidden service");
|
log.debug("[simulation] Create hidden service");
|
||||||
if (simulateTorDelayHiddenService > 0) Thread.sleep(simulateTorDelayHiddenService);
|
if (simulateTorDelayHiddenService > 0) Thread.sleep(simulateTorDelayHiddenService);
|
||||||
log.debug("\n\n##### Hidden service created [simulation]. Took " + (System.currentTimeMillis() - ts) + " ms\n\n");
|
log.info("\n\n############################################################\n" +
|
||||||
|
"Hidden service created [simulation]:" +
|
||||||
|
"\nTook " + (System.currentTimeMillis() - ts) + " ms"
|
||||||
|
+ "\n############################################################\n");
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
ListenableFuture<HiddenServiceDescriptor> future = executorService.submit(task);
|
ListenableFuture<HiddenServiceDescriptor> future = executorService.submit(task);
|
||||||
|
|
|
@ -11,9 +11,11 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
@ -22,9 +24,8 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
private static final Logger log = LoggerFactory.getLogger(NetworkNode.class);
|
private static final Logger log = LoggerFactory.getLogger(NetworkNode.class);
|
||||||
|
|
||||||
protected final int port;
|
protected final int port;
|
||||||
private final Map<Address, Connection> outBoundConnections = new ConcurrentHashMap<>();
|
private final List<Connection> outBoundConnections = new CopyOnWriteArrayList<>();
|
||||||
private final Map<Address, Connection> inBoundAuthenticatedConnections = new ConcurrentHashMap<>();
|
private final List<Connection> inBoundConnections = new CopyOnWriteArrayList<>();
|
||||||
private final List<Connection> inBoundTempConnections = new CopyOnWriteArrayList<>();
|
|
||||||
private final List<MessageListener> messageListeners = new CopyOnWriteArrayList<>();
|
private final List<MessageListener> messageListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<ConnectionListener> connectionListeners = new CopyOnWriteArrayList<>();
|
private final List<ConnectionListener> connectionListeners = new CopyOnWriteArrayList<>();
|
||||||
protected final List<SetupListener> setupListeners = new CopyOnWriteArrayList<>();
|
protected final List<SetupListener> setupListeners = new CopyOnWriteArrayList<>();
|
||||||
|
@ -58,32 +59,21 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
|
|
||||||
Callable<Connection> task = () -> {
|
Callable<Connection> task = () -> {
|
||||||
Thread.currentThread().setName("Outgoing-connection-to-" + peerAddress);
|
Thread.currentThread().setName("Outgoing-connection-to-" + peerAddress);
|
||||||
Connection connection = outBoundConnections.get(peerAddress);
|
|
||||||
|
Optional<Connection> outboundConnectionOptional = getOutboundConnection(peerAddress);
|
||||||
|
Connection connection = outboundConnectionOptional.isPresent() ? outboundConnectionOptional.get() : null;
|
||||||
|
|
||||||
if (connection != null && connection.isStopped()) {
|
if (connection != null && connection.isStopped()) {
|
||||||
// can happen because of threading...
|
|
||||||
log.trace("We have a connection which is already stopped in outBoundConnections. Connection.uid=" + connection.getUid());
|
log.trace("We have a connection which is already stopped in outBoundConnections. Connection.uid=" + connection.getUid());
|
||||||
outBoundConnections.remove(peerAddress);
|
outBoundConnections.remove(connection);
|
||||||
connection = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection == null) {
|
if (connection == null) {
|
||||||
Optional<Connection> connectionOptional = inBoundAuthenticatedConnections.values().stream()
|
Optional<Connection> inboundConnectionOptional = getInboundConnection(peerAddress);
|
||||||
.filter(e -> peerAddress.equals(e.getPeerAddress()))
|
if (inboundConnectionOptional.isPresent()) connection = inboundConnectionOptional.get();
|
||||||
.findAny();
|
|
||||||
if (connectionOptional.isPresent())
|
|
||||||
connection = connectionOptional.get();
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
log.trace("We have found a connection in inBoundAuthenticatedConnections. Connection.uid=" + connection.getUid());
|
log.trace("We have found a connection in inBoundConnections. Connection.uid=" + connection.getUid());
|
||||||
}
|
|
||||||
if (connection == null) {
|
|
||||||
Optional<Connection> connectionOptional = inBoundTempConnections.stream()
|
|
||||||
.filter(e -> peerAddress.equals(e.getPeerAddress()))
|
|
||||||
.findAny();
|
|
||||||
if (connectionOptional.isPresent())
|
|
||||||
connection = connectionOptional.get();
|
|
||||||
if (connection != null)
|
|
||||||
log.trace("We have found a connection in inBoundTempConnections. Connection.uid=" + connection.getUid());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection == null) {
|
if (connection == null) {
|
||||||
|
@ -113,7 +103,11 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
NetworkNode.this.onError(throwable);
|
NetworkNode.this.onError(throwable);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
outBoundConnections.put(peerAddress, connection);
|
if (!outBoundConnections.contains(connection))
|
||||||
|
outBoundConnections.add(connection);
|
||||||
|
else
|
||||||
|
log.error("We have already that connection in our list. That must not happen. "
|
||||||
|
+ outBoundConnections + " / connection=" + connection);
|
||||||
|
|
||||||
log.info("\n\nNetworkNode created new outbound connection:"
|
log.info("\n\nNetworkNode created new outbound connection:"
|
||||||
+ "\npeerAddress=" + peerAddress.port
|
+ "\npeerAddress=" + peerAddress.port
|
||||||
|
@ -144,6 +138,16 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
return resultFuture;
|
return resultFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<Connection> getOutboundConnection(Address peerAddress) {
|
||||||
|
return outBoundConnections.stream()
|
||||||
|
.filter(e -> peerAddress.equals(e.getPeerAddress())).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Connection> getInboundConnection(Address peerAddress) {
|
||||||
|
return inBoundConnections.stream()
|
||||||
|
.filter(e -> peerAddress.equals(e.getPeerAddress())).findAny();
|
||||||
|
}
|
||||||
|
|
||||||
public SettableFuture<Connection> sendMessage(Connection connection, Message message) {
|
public SettableFuture<Connection> sendMessage(Connection connection, Message message) {
|
||||||
final SettableFuture<Connection> resultFuture = SettableFuture.create();
|
final SettableFuture<Connection> resultFuture = SettableFuture.create();
|
||||||
|
|
||||||
|
@ -164,9 +168,8 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Connection> getAllConnections() {
|
public Set<Connection> getAllConnections() {
|
||||||
Set<Connection> set = new HashSet<>(inBoundAuthenticatedConnections.values());
|
Set<Connection> set = new HashSet<>(inBoundConnections);
|
||||||
set.addAll(outBoundConnections.values());
|
set.addAll(outBoundConnections);
|
||||||
set.addAll(inBoundTempConnections);
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,22 +229,8 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
Address peerAddress = connection.getPeerAddress();
|
Address peerAddress = connection.getPeerAddress();
|
||||||
log.trace("onDisconnect connection " + connection + ", peerAddress= " + peerAddress);
|
log.trace("onDisconnect connection " + connection + ", peerAddress= " + peerAddress);
|
||||||
if (peerAddress != null) {
|
outBoundConnections.remove(connection);
|
||||||
inBoundAuthenticatedConnections.remove(peerAddress);
|
inBoundConnections.remove(connection);
|
||||||
outBoundConnections.remove(peerAddress);
|
|
||||||
} else {
|
|
||||||
// try to find if we have connection
|
|
||||||
outBoundConnections.values().stream()
|
|
||||||
.filter(e -> e.equals(connection))
|
|
||||||
.findAny()
|
|
||||||
.ifPresent(e -> outBoundConnections.remove(e.getPeerAddress()));
|
|
||||||
inBoundAuthenticatedConnections.values().stream()
|
|
||||||
.filter(e -> e.equals(connection))
|
|
||||||
.findAny()
|
|
||||||
.ifPresent(e -> inBoundAuthenticatedConnections.remove(e.getPeerAddress()));
|
|
||||||
}
|
|
||||||
inBoundTempConnections.remove(connection);
|
|
||||||
|
|
||||||
connectionListeners.stream().forEach(e -> e.onDisconnect(reason, connection));
|
connectionListeners.stream().forEach(e -> e.onDisconnect(reason, connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,28 +269,21 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
@Override
|
@Override
|
||||||
public void onConnection(Connection connection) {
|
public void onConnection(Connection connection) {
|
||||||
// we still have not authenticated so put it to the temp list
|
// we still have not authenticated so put it to the temp list
|
||||||
inBoundTempConnections.add(connection);
|
if (!inBoundConnections.contains(connection))
|
||||||
|
inBoundConnections.add(connection);
|
||||||
NetworkNode.this.onConnection(connection);
|
NetworkNode.this.onConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPeerAddressAuthenticated(Address peerAddress, Connection connection) {
|
public void onPeerAddressAuthenticated(Address peerAddress, Connection connection) {
|
||||||
NetworkNode.this.onPeerAddressAuthenticated(peerAddress, connection);
|
NetworkNode.this.onPeerAddressAuthenticated(peerAddress, connection);
|
||||||
// now we know the the peers address is correct and we add it to inBoundConnections and
|
|
||||||
// remove it from tempConnections
|
|
||||||
inBoundAuthenticatedConnections.put(peerAddress, connection);
|
|
||||||
inBoundTempConnections.remove(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
Address peerAddress = connection.getPeerAddress();
|
Address peerAddress = connection.getPeerAddress();
|
||||||
log.trace("onDisconnect at incoming connection to peerAddress " + peerAddress);
|
log.trace("onDisconnect at incoming connection to peerAddress " + peerAddress);
|
||||||
if (peerAddress != null)
|
inBoundConnections.remove(connection);
|
||||||
inBoundAuthenticatedConnections.remove(peerAddress);
|
|
||||||
|
|
||||||
inBoundTempConnections.remove(connection);
|
|
||||||
|
|
||||||
NetworkNode.this.onDisconnect(reason, connection);
|
NetworkNode.this.onDisconnect(reason, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class TorNetworkNode extends NetworkNode {
|
||||||
private Timer shutDownTimeoutTimer, selfTestTimer, selfTestTimeoutTimer;
|
private Timer shutDownTimeoutTimer, selfTestTimer, selfTestTimeoutTimer;
|
||||||
private TimerTask selfTestTimeoutTask, selfTestTask;
|
private TimerTask selfTestTimeoutTask, selfTestTask;
|
||||||
private AtomicBoolean selfTestRunning = new AtomicBoolean(false);
|
private AtomicBoolean selfTestRunning = new AtomicBoolean(false);
|
||||||
private int nonce;
|
private long nonce;
|
||||||
private int errorCounter;
|
private int errorCounter;
|
||||||
private int restartCounter;
|
private int restartCounter;
|
||||||
private Runnable shutDownCompleteHandler;
|
private Runnable shutDownCompleteHandler;
|
||||||
|
@ -79,7 +79,7 @@ public class TorNetworkNode extends NetworkNode {
|
||||||
selfTestTimeoutTimer.schedule(selfTestTimeoutTask, TIMEOUT);
|
selfTestTimeoutTimer.schedule(selfTestTimeoutTask, TIMEOUT);
|
||||||
// might be interrupted by timeout task
|
// might be interrupted by timeout task
|
||||||
if (selfTestRunning.get()) {
|
if (selfTestRunning.get()) {
|
||||||
nonce = random.nextInt();
|
nonce = random.nextLong();
|
||||||
log.trace("send msg with nonce " + nonce);
|
log.trace("send msg with nonce " + nonce);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -281,7 +281,10 @@ public class TorNetworkNode extends NetworkNode {
|
||||||
TorNode<JavaOnionProxyManager, JavaOnionProxyContext> torNode1 = new TorNode<JavaOnionProxyManager, JavaOnionProxyContext>(
|
TorNode<JavaOnionProxyManager, JavaOnionProxyContext> torNode1 = new TorNode<JavaOnionProxyManager, JavaOnionProxyContext>(
|
||||||
torDir) {
|
torDir) {
|
||||||
};
|
};
|
||||||
log.trace("\n\n##### TorNode created. Took " + (System.currentTimeMillis() - ts) + " ms\n\n");
|
log.info("\n\n############################################################\n" +
|
||||||
|
"TorNode created:" +
|
||||||
|
"\nTook " + (System.currentTimeMillis() - ts) + " ms"
|
||||||
|
+ "\n############################################################\n");
|
||||||
return torNode1;
|
return torNode1;
|
||||||
};
|
};
|
||||||
ListenableFuture<TorNode<JavaOnionProxyManager, JavaOnionProxyContext>> future = executorService.submit(task);
|
ListenableFuture<TorNode<JavaOnionProxyManager, JavaOnionProxyContext>> future = executorService.submit(task);
|
||||||
|
@ -303,7 +306,11 @@ public class TorNetworkNode extends NetworkNode {
|
||||||
long ts = System.currentTimeMillis();
|
long ts = System.currentTimeMillis();
|
||||||
log.debug("Create hidden service");
|
log.debug("Create hidden service");
|
||||||
HiddenServiceDescriptor hiddenServiceDescriptor = torNode.createHiddenService(port);
|
HiddenServiceDescriptor hiddenServiceDescriptor = torNode.createHiddenService(port);
|
||||||
log.debug("\n\n##### Hidden service created. Address = " + hiddenServiceDescriptor.getFullAddress() + ". Took " + (System.currentTimeMillis() - ts) + " ms\n\n");
|
log.info("\n\n############################################################\n" +
|
||||||
|
"Hidden service created:" +
|
||||||
|
"\nAddress=" + hiddenServiceDescriptor.getFullAddress() +
|
||||||
|
"\nTook " + (System.currentTimeMillis() - ts) + " ms"
|
||||||
|
+ "\n############################################################\n");
|
||||||
|
|
||||||
return hiddenServiceDescriptor;
|
return hiddenServiceDescriptor;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,9 +7,9 @@ public final class SelfTestMessage implements Message {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final Integer nonce;
|
public final long nonce;
|
||||||
|
|
||||||
public SelfTestMessage(Integer nonce) {
|
public SelfTestMessage(long nonce) {
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,37 @@
|
||||||
package io.bitsquare.p2p.routing;
|
package io.bitsquare.p2p.routing;
|
||||||
|
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
|
import io.bitsquare.p2p.network.Connection;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class Neighbor implements Serializable {
|
public class Neighbor implements Serializable {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Neighbor.class);
|
private static final Logger log = LoggerFactory.getLogger(Neighbor.class);
|
||||||
|
|
||||||
|
public final Connection connection;
|
||||||
public final Address address;
|
public final Address address;
|
||||||
private int pingNonce;
|
private long pingNonce;
|
||||||
|
|
||||||
public Neighbor(Address address) {
|
public Neighbor(Connection connection) {
|
||||||
this.address = address;
|
this.connection = connection;
|
||||||
|
this.address = connection.getPeerAddress();
|
||||||
|
pingNonce = new Random().nextLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPingNonce(int pingNonce) {
|
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
this.pingNonce = pingNonce;
|
try {
|
||||||
|
in.defaultReadObject();
|
||||||
|
pingNonce = new Random().nextLong();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
log.trace("Cannot be deserialized." + t.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPingNonce() {
|
public long getPingNonce() {
|
||||||
return pingNonce;
|
return pingNonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,15 @@ import java.util.stream.Collectors;
|
||||||
public class Routing {
|
public class Routing {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Routing.class);
|
private static final Logger log = LoggerFactory.getLogger(Routing.class);
|
||||||
|
|
||||||
|
private static int simulateAuthTorNode = 2 * 1000;
|
||||||
|
|
||||||
|
public static void setSimulateAuthTorNode(int simulateAuthTorNode) {
|
||||||
|
Routing.simulateAuthTorNode = simulateAuthTorNode;
|
||||||
|
}
|
||||||
|
|
||||||
private static int MAX_CONNECTIONS = 8;
|
private static int MAX_CONNECTIONS = 8;
|
||||||
|
private static int MAINTENANCE_INTERVAL = new Random().nextInt(15 * 60 * 1000) + 15 * 60 * 1000; // 15-30 min.
|
||||||
|
private static int PING_AFTER_CONNECTION_INACTIVITY = 5 * 60 * 1000; // 5 min
|
||||||
private long startAuthTs;
|
private long startAuthTs;
|
||||||
|
|
||||||
public static void setMaxConnections(int maxConnections) {
|
public static void setMaxConnections(int maxConnections) {
|
||||||
|
@ -33,10 +41,10 @@ public class Routing {
|
||||||
|
|
||||||
private final NetworkNode networkNode;
|
private final NetworkNode networkNode;
|
||||||
private final List<Address> seedNodes;
|
private final List<Address> seedNodes;
|
||||||
private final Map<Address, Integer> nonceMap = new ConcurrentHashMap<>();
|
private final Map<Address, Long> nonceMap = new ConcurrentHashMap<>();
|
||||||
private final List<RoutingListener> routingListeners = new CopyOnWriteArrayList<>();
|
private final List<RoutingListener> routingListeners = new CopyOnWriteArrayList<>();
|
||||||
private final Map<Address, Neighbor> connectedNeighbors = new ConcurrentHashMap<>();
|
private final Map<Address, Neighbor> connectedNeighbors = new ConcurrentHashMap<>();
|
||||||
private final Map<Address, Neighbor> reportedNeighbors = new ConcurrentHashMap<>();
|
private final List<Address> reportedNeighborAddresses = new CopyOnWriteArrayList<>();
|
||||||
private final Map<Address, Runnable> authenticationCompleteHandlers = new ConcurrentHashMap<>();
|
private final Map<Address, Runnable> authenticationCompleteHandlers = new ConcurrentHashMap<>();
|
||||||
private final Timer maintenanceTimer = new Timer();
|
private final Timer maintenanceTimer = new Timer();
|
||||||
private final ExecutorService executorService = Executors.newCachedThreadPool();
|
private final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
@ -72,7 +80,7 @@ public class Routing {
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
// only removes authenticated nodes
|
// only removes authenticated nodes
|
||||||
if (connection.getPeerAddress() != null)
|
if (connection.isAuthenticated())
|
||||||
removeNeighbor(connection.getPeerAddress());
|
removeNeighbor(connection.getPeerAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +107,13 @@ public class Routing {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
int maintenanceInterval = new Random().nextInt(15 * 60 * 1000) + 15 * 60 * 1000; // 15-30 min.
|
|
||||||
maintenanceTimer.scheduleAtFixedRate(new TimerTask() {
|
maintenanceTimer.scheduleAtFixedRate(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
disconnectOldConnections();
|
disconnectOldConnections();
|
||||||
pingNeighbors();
|
pingNeighbors();
|
||||||
}
|
}
|
||||||
}, maintenanceInterval, maintenanceInterval);
|
}, MAINTENANCE_INTERVAL, MAINTENANCE_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disconnectOldConnections() {
|
private void disconnectOldConnections() {
|
||||||
|
@ -128,7 +135,30 @@ public class Routing {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pingNeighbors() {
|
private void pingNeighbors() {
|
||||||
|
log.trace("pingNeighbors");
|
||||||
|
List<Neighbor> connectedNeighborsList = new ArrayList<>(connectedNeighbors.values());
|
||||||
|
connectedNeighborsList.stream()
|
||||||
|
.filter(e -> (new Date().getTime() - e.connection.getLastActivityDate().getTime()) > PING_AFTER_CONNECTION_INACTIVITY)
|
||||||
|
.forEach(e -> {
|
||||||
|
SettableFuture<Connection> future = networkNode.sendMessage(e.connection, new PingMessage(e.getPingNonce()));
|
||||||
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Connection connection) {
|
||||||
|
log.trace("PingMessage sent successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NotNull Throwable throwable) {
|
||||||
|
log.info("PingMessage sending failed " + throwable.getMessage());
|
||||||
|
removeNeighbor(e.address);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
Thread.sleep(new Random().nextInt(5000) + 5000);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,12 +176,13 @@ public class Routing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(BroadcastMessage message, Address sender) {
|
public void broadcast(BroadcastMessage message, @Nullable Address sender) {
|
||||||
log.trace("Broadcast message to " + connectedNeighbors.values().size() + " neighbors.");
|
log.trace("Broadcast message to " + connectedNeighbors.values().size() + " neighbors.");
|
||||||
|
log.trace("message = " + message);
|
||||||
connectedNeighbors.values().parallelStream()
|
connectedNeighbors.values().parallelStream()
|
||||||
.filter(e -> !e.address.equals(sender))
|
.filter(e -> !e.address.equals(sender))
|
||||||
.forEach(neighbor -> {
|
.forEach(neighbor -> {
|
||||||
log.trace("Broadcast message " + message + " from " + getAddress() + " to " + neighbor.address + ".");
|
log.trace("Broadcast message from " + getAddress() + " to " + neighbor.address + ".");
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(neighbor.address, message);
|
SettableFuture<Connection> future = networkNode.sendMessage(neighbor.address, message);
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -184,20 +215,18 @@ public class Routing {
|
||||||
routingListeners.remove(routingListener);
|
routingListeners.remove(routingListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Address, Neighbor> getReportedNeighbors() {
|
|
||||||
return reportedNeighbors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Address, Neighbor> getConnectedNeighbors() {
|
public Map<Address, Neighbor> getConnectedNeighbors() {
|
||||||
return connectedNeighbors;
|
return connectedNeighbors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Address, Neighbor> getAllNeighbors() {
|
// Use ArrayList not List as we need it serializable
|
||||||
Map<Address, Neighbor> hashMap = new ConcurrentHashMap<>(reportedNeighbors);
|
public ArrayList<Address> getAllNeighborAddresses() {
|
||||||
hashMap.putAll(connectedNeighbors);
|
ArrayList<Address> allNeighborAddresses = new ArrayList<>(reportedNeighborAddresses);
|
||||||
|
allNeighborAddresses.addAll(connectedNeighbors.values().stream()
|
||||||
|
.map(e -> e.address).collect(Collectors.toList()));
|
||||||
// remove own address and seed nodes
|
// remove own address and seed nodes
|
||||||
hashMap.remove(getAddress());
|
allNeighborAddresses.remove(getAddress());
|
||||||
return hashMap;
|
return allNeighborAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,7 +268,7 @@ public class Routing {
|
||||||
alreadyConnected[0] = true;
|
alreadyConnected[0] = true;
|
||||||
});
|
});
|
||||||
if (!alreadyConnected[0]) {
|
if (!alreadyConnected[0]) {
|
||||||
int nonce = addToMapAndGetNonce(address);
|
long nonce = addToMapAndGetNonce(address);
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(address, new RequestAuthenticationMessage(getAddress(), nonce));
|
SettableFuture<Connection> future = networkNode.sendMessage(address, new RequestAuthenticationMessage(getAddress(), nonce));
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -287,12 +316,17 @@ public class Routing {
|
||||||
// inconsistent state (removal of connection from NetworkNode.authenticatedConnections)
|
// inconsistent state (removal of connection from NetworkNode.authenticatedConnections)
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (simulateAuthTorNode > 0) Thread.sleep(simulateAuthTorNode);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
log.trace("processAuthenticationMessage: connection.shutDown complete. RequestAuthenticationMessage from " + peerAddress + " at " + getAddress());
|
log.trace("processAuthenticationMessage: connection.shutDown complete. RequestAuthenticationMessage from " + peerAddress + " at " + getAddress());
|
||||||
int nonce = addToMapAndGetNonce(peerAddress);
|
long nonce = addToMapAndGetNonce(peerAddress);
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, new ChallengeMessage(getAddress(), requestAuthenticationMessage.nonce, nonce));
|
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, new ChallengeMessage(getAddress(), requestAuthenticationMessage.nonce, nonce));
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -324,12 +358,12 @@ public class Routing {
|
||||||
} else if (message instanceof ChallengeMessage) {
|
} else if (message instanceof ChallengeMessage) {
|
||||||
ChallengeMessage challengeMessage = (ChallengeMessage) message;
|
ChallengeMessage challengeMessage = (ChallengeMessage) message;
|
||||||
Address peerAddress = challengeMessage.address;
|
Address peerAddress = challengeMessage.address;
|
||||||
connection.setPeerAddress(peerAddress);
|
|
||||||
log.trace("ChallengeMessage from " + peerAddress + " at " + getAddress());
|
log.trace("ChallengeMessage from " + peerAddress + " at " + getAddress());
|
||||||
|
HashMap<Address, Long> tempNonceMap = new HashMap<>(nonceMap);
|
||||||
boolean verified = verifyNonceAndAuthenticatePeerAddress(challengeMessage.requesterNonce, peerAddress);
|
boolean verified = verifyNonceAndAuthenticatePeerAddress(challengeMessage.requesterNonce, peerAddress);
|
||||||
if (verified) {
|
if (verified) {
|
||||||
HashMap<Address, Neighbor> allNeighbors = new HashMap<>(getAllNeighbors());
|
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress,
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, new GetNeighborsMessage(getAddress(), challengeMessage.challengerNonce, allNeighbors));
|
new GetNeighborsMessage(getAddress(), challengeMessage.challengerNonce, getAllNeighborAddresses()));
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Connection connection) {
|
public void onSuccess(Connection connection) {
|
||||||
|
@ -346,6 +380,8 @@ public class Routing {
|
||||||
removeNeighbor(peerAddress);
|
removeNeighbor(peerAddress);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
log.warn("verifyNonceAndAuthenticatePeerAddress failed. challengeMessage=" + challengeMessage + " / nonceMap=" + tempNonceMap);
|
||||||
}
|
}
|
||||||
} else if (message instanceof GetNeighborsMessage) {
|
} else if (message instanceof GetNeighborsMessage) {
|
||||||
GetNeighborsMessage getNeighborsMessage = (GetNeighborsMessage) message;
|
GetNeighborsMessage getNeighborsMessage = (GetNeighborsMessage) message;
|
||||||
|
@ -355,9 +391,10 @@ public class Routing {
|
||||||
if (verified) {
|
if (verified) {
|
||||||
setAuthenticated(connection, peerAddress);
|
setAuthenticated(connection, peerAddress);
|
||||||
purgeReportedNeighbors();
|
purgeReportedNeighbors();
|
||||||
HashMap<Address, Neighbor> allNeighbors = new HashMap<>(getAllNeighbors());
|
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress,
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, new NeighborsMessage(allNeighbors));
|
new NeighborsMessage(getAllNeighborAddresses()));
|
||||||
log.trace("sent NeighborsMessage to " + peerAddress + " from " + getAddress() + " with allNeighbors=" + allNeighbors.values());
|
log.trace("sent NeighborsMessage to " + peerAddress + " from " + getAddress()
|
||||||
|
+ " with allNeighbors=" + getAllNeighborAddresses());
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Connection connection) {
|
public void onSuccess(Connection connection) {
|
||||||
|
@ -372,19 +409,19 @@ public class Routing {
|
||||||
});
|
});
|
||||||
|
|
||||||
// now we add the reported neighbors to our own set
|
// now we add the reported neighbors to our own set
|
||||||
final HashMap<Address, Neighbor> neighbors = ((GetNeighborsMessage) message).neighbors;
|
ArrayList<Address> neighborAddresses = ((GetNeighborsMessage) message).neighborAddresses;
|
||||||
log.trace("Received neighbors: " + neighbors);
|
log.trace("Received neighbors: " + neighborAddresses);
|
||||||
// remove ourselves
|
// remove ourselves
|
||||||
neighbors.remove(getAddress());
|
neighborAddresses.remove(getAddress());
|
||||||
addToReportedNeighbors(neighbors, connection);
|
addToReportedNeighbors(neighborAddresses, connection);
|
||||||
}
|
}
|
||||||
} else if (message instanceof NeighborsMessage) {
|
} else if (message instanceof NeighborsMessage) {
|
||||||
log.trace("NeighborsMessage from " + connection.getPeerAddress() + " at " + getAddress());
|
log.trace("NeighborsMessage from " + connection.getPeerAddress() + " at " + getAddress());
|
||||||
final HashMap<Address, Neighbor> neighbors = ((NeighborsMessage) message).neighbors;
|
ArrayList<Address> neighborAddresses = ((NeighborsMessage) message).neighborAddresses;
|
||||||
log.trace("Received neighbors: " + neighbors);
|
log.trace("Received neighbors: " + neighborAddresses);
|
||||||
// remove ourselves
|
// remove ourselves
|
||||||
neighbors.remove(getAddress());
|
neighborAddresses.remove(getAddress());
|
||||||
addToReportedNeighbors(neighbors, connection);
|
addToReportedNeighbors(neighborAddresses, connection);
|
||||||
|
|
||||||
log.info("\n\nAuthenticationComplete\nPeer with address " + connection.getPeerAddress().toString()
|
log.info("\n\nAuthenticationComplete\nPeer with address " + connection.getPeerAddress().toString()
|
||||||
+ " authenticated (" + connection.getObjectId() + "). Took "
|
+ " authenticated (" + connection.getObjectId() + "). Took "
|
||||||
|
@ -398,36 +435,42 @@ public class Routing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToReportedNeighbors(HashMap<Address, Neighbor> neighbors, Connection connection) {
|
private void addToReportedNeighbors(ArrayList<Address> neighborAddresses, Connection connection) {
|
||||||
// we disconnect misbehaving nodes trying to send too many neighbors
|
// we disconnect misbehaving nodes trying to send too many neighbors
|
||||||
// reported neighbors include the peers connected neighbors which is normally max. 8 but we give some headroom
|
// reported neighbors include the peers connected neighbors which is normally max. 8 but we give some headroom
|
||||||
// for safety
|
// for safety
|
||||||
if (neighbors.size() > 1100) {
|
if (neighborAddresses.size() > 1100) {
|
||||||
connection.shutDown();
|
connection.shutDown();
|
||||||
} else {
|
} else {
|
||||||
reportedNeighbors.putAll(neighbors);
|
reportedNeighborAddresses.addAll(neighborAddresses);
|
||||||
purgeReportedNeighbors();
|
purgeReportedNeighbors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void purgeReportedNeighbors() {
|
private void purgeReportedNeighbors() {
|
||||||
int all = getAllNeighbors().size();
|
int all = getAllNeighborAddresses().size();
|
||||||
if (all > 1000) {
|
if (all > 1000) {
|
||||||
int diff = all - 100;
|
int diff = all - 100;
|
||||||
ArrayList<Neighbor> reportedNeighborsList = new ArrayList<>(reportedNeighbors.values());
|
List<Address> list = getNotConnectedNeighborAddresses();
|
||||||
for (int i = 0; i < diff; i++) {
|
for (int i = 0; i < diff; i++) {
|
||||||
Neighbor neighborToRemove = reportedNeighborsList.remove(new Random().nextInt(reportedNeighborsList.size()));
|
Address neighborToRemove = list.remove(new Random().nextInt(list.size()));
|
||||||
reportedNeighbors.remove(neighborToRemove.address);
|
reportedNeighborAddresses.remove(neighborToRemove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Address> getNotConnectedNeighborAddresses() {
|
||||||
|
ArrayList<Address> reportedNeighborsList = new ArrayList<>(getAllNeighborAddresses());
|
||||||
|
connectedNeighbors.values().stream().forEach(e -> reportedNeighborsList.remove(e.address));
|
||||||
|
return reportedNeighborsList;
|
||||||
|
}
|
||||||
|
|
||||||
private void authenticateToNextRandomNeighbor() {
|
private void authenticateToNextRandomNeighbor() {
|
||||||
if (getConnectedNeighbors().size() <= MAX_CONNECTIONS) {
|
if (getConnectedNeighbors().size() <= MAX_CONNECTIONS) {
|
||||||
Neighbor randomNotConnectedNeighbor = getRandomNotConnectedNeighbor();
|
Address randomNotConnectedNeighborAddress = getRandomNotConnectedNeighborAddress();
|
||||||
if (randomNotConnectedNeighbor != null) {
|
if (randomNotConnectedNeighborAddress != null) {
|
||||||
log.info("We try to build an authenticated connection to a random neighbor. " + randomNotConnectedNeighbor);
|
log.info("We try to build an authenticated connection to a random neighbor. " + randomNotConnectedNeighborAddress);
|
||||||
authenticateToPeer(randomNotConnectedNeighbor.address, null, () -> authenticateToNextRandomNeighbor());
|
authenticateToPeer(randomNotConnectedNeighborAddress, null, () -> authenticateToNextRandomNeighbor());
|
||||||
} else {
|
} else {
|
||||||
log.info("No more neighbors available for connecting.");
|
log.info("No more neighbors available for connecting.");
|
||||||
}
|
}
|
||||||
|
@ -442,7 +485,7 @@ public class Routing {
|
||||||
if (authenticationCompleteHandler != null)
|
if (authenticationCompleteHandler != null)
|
||||||
authenticationCompleteHandlers.put(address, authenticationCompleteHandler);
|
authenticationCompleteHandlers.put(address, authenticationCompleteHandler);
|
||||||
|
|
||||||
int nonce = addToMapAndGetNonce(address);
|
long nonce = addToMapAndGetNonce(address);
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(address, new RequestAuthenticationMessage(getAddress(), nonce));
|
SettableFuture<Connection> future = networkNode.sendMessage(address, new RequestAuthenticationMessage(getAddress(), nonce));
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -459,34 +502,43 @@ public class Routing {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addToMapAndGetNonce(Address address) {
|
private long addToMapAndGetNonce(Address peerAddress) {
|
||||||
int nonce = new Random().nextInt();
|
long nonce = new Random().nextLong();
|
||||||
while (nonce == 0) {
|
while (nonce == 0) {
|
||||||
nonce = new Random().nextInt();
|
nonce = new Random().nextLong();
|
||||||
}
|
}
|
||||||
nonceMap.put(address, nonce);
|
log.trace("addToMapAndGetNonce nonceMap=" + nonceMap + " / peerAddress=" + peerAddress);
|
||||||
|
nonceMap.put(peerAddress, nonce);
|
||||||
return nonce;
|
return nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean verifyNonceAndAuthenticatePeerAddress(int peersNonce, Address peerAddress) {
|
private boolean verifyNonceAndAuthenticatePeerAddress(long peersNonce, Address peerAddress) {
|
||||||
int nonce = nonceMap.remove(peerAddress);
|
log.trace("verifyNonceAndAuthenticatePeerAddress nonceMap=" + nonceMap + " / peerAddress=" + peerAddress);
|
||||||
|
long nonce = nonceMap.remove(peerAddress);
|
||||||
boolean result = nonce == peersNonce;
|
boolean result = nonce == peersNonce;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAuthenticated(Connection connection, Address address) {
|
private void setAuthenticated(Connection connection, Address peerAddress) {
|
||||||
log.info("We got the connection from " + getAddress() + " to " + address + " authenticated.");
|
log.info("\n\n############################################################\n" +
|
||||||
Neighbor neighbor = new Neighbor(address);
|
"We are authenticated to:" +
|
||||||
addConnectedNeighbor(address, neighbor);
|
"\nconnection=" + connection
|
||||||
|
+ "\nmyAddress=" + getAddress()
|
||||||
|
+ "\npeerAddress= " + peerAddress
|
||||||
|
+ "\n############################################################\n");
|
||||||
|
|
||||||
|
connection.onAuthenticationComplete(peerAddress, connection);
|
||||||
|
|
||||||
|
Neighbor neighbor = new Neighbor(connection);
|
||||||
|
addConnectedNeighbor(peerAddress, neighbor);
|
||||||
|
|
||||||
connection.onAuthenticationComplete(address, connection);
|
|
||||||
routingListeners.stream().forEach(e -> e.onConnectionAuthenticated(connection));
|
routingListeners.stream().forEach(e -> e.onConnectionAuthenticated(connection));
|
||||||
|
|
||||||
|
log.debug("\n### setAuthenticated post connection " + connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Neighbor getRandomNotConnectedNeighbor() {
|
private Address getRandomNotConnectedNeighborAddress() {
|
||||||
List<Neighbor> list = reportedNeighbors.values().stream()
|
List<Address> list = getNotConnectedNeighborAddresses();
|
||||||
.filter(e -> !connectedNeighbors.values().contains(e))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
Collections.shuffle(list);
|
Collections.shuffle(list);
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
|
@ -532,16 +584,17 @@ public class Routing {
|
||||||
// Neighbors
|
// Neighbors
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void removeNeighbor(Address address) {
|
private void removeNeighbor(@Nullable Address peerAddress) {
|
||||||
reportedNeighbors.remove(address);
|
reportedNeighborAddresses.remove(peerAddress);
|
||||||
|
|
||||||
Neighbor disconnectedNeighbor;
|
Neighbor disconnectedNeighbor;
|
||||||
disconnectedNeighbor = connectedNeighbors.remove(address);
|
disconnectedNeighbor = connectedNeighbors.remove(peerAddress);
|
||||||
|
|
||||||
if (disconnectedNeighbor != null)
|
if (disconnectedNeighbor != null)
|
||||||
UserThread.execute(() -> routingListeners.stream().forEach(e -> e.onNeighborRemoved(address)));
|
UserThread.execute(() -> routingListeners.stream().forEach(e -> e.onNeighborRemoved(peerAddress)));
|
||||||
|
|
||||||
nonceMap.remove(address);
|
log.trace("removeNeighbor nonceMap=" + nonceMap + " / peerAddress=" + peerAddress);
|
||||||
|
nonceMap.remove(peerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConnectedNeighbor(Address address, Neighbor neighbor) {
|
private void addConnectedNeighbor(Address address, Neighbor neighbor) {
|
||||||
|
@ -577,9 +630,9 @@ public class Routing {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printReportedNeighborsMap() {
|
public void printReportedNeighborsMap() {
|
||||||
StringBuilder result = new StringBuilder("\nReported neighbors for node " + getAddress() + ":");
|
StringBuilder result = new StringBuilder("\nReported neighborAddresses for node " + getAddress() + ":");
|
||||||
reportedNeighbors.values().stream().forEach(e -> {
|
reportedNeighborAddresses.stream().forEach(e -> {
|
||||||
result.append("\n\t" + e.address);
|
result.append("\n\t" + e);
|
||||||
});
|
});
|
||||||
result.append("\n");
|
result.append("\n");
|
||||||
log.info(result.toString());
|
log.info(result.toString());
|
||||||
|
|
|
@ -8,10 +8,10 @@ public final class ChallengeMessage implements AuthenticationMessage {
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final Address address;
|
public final Address address;
|
||||||
public final int requesterNonce;
|
public final long requesterNonce;
|
||||||
public final int challengerNonce;
|
public final long challengerNonce;
|
||||||
|
|
||||||
public ChallengeMessage(Address address, int requesterNonce, int challengerNonce) {
|
public ChallengeMessage(Address address, long requesterNonce, long challengerNonce) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.requesterNonce = requesterNonce;
|
this.requesterNonce = requesterNonce;
|
||||||
this.challengerNonce = challengerNonce;
|
this.challengerNonce = challengerNonce;
|
||||||
|
|
|
@ -2,22 +2,21 @@ package io.bitsquare.p2p.routing.messages;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.routing.Neighbor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class GetNeighborsMessage implements AuthenticationMessage {
|
public final class GetNeighborsMessage implements AuthenticationMessage {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final Address address;
|
public final Address address;
|
||||||
public final int challengerNonce;
|
public final long challengerNonce;
|
||||||
public final HashMap<Address, Neighbor> neighbors;
|
public final ArrayList<Address> neighborAddresses;
|
||||||
|
|
||||||
public GetNeighborsMessage(Address address, int challengerNonce, HashMap<Address, Neighbor> neighbors) {
|
public GetNeighborsMessage(Address address, long challengerNonce, ArrayList<Address> neighborAddresses) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.challengerNonce = challengerNonce;
|
this.challengerNonce = challengerNonce;
|
||||||
this.neighbors = neighbors;
|
this.neighborAddresses = neighborAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +24,7 @@ public final class GetNeighborsMessage implements AuthenticationMessage {
|
||||||
return "GetNeighborsMessage{" +
|
return "GetNeighborsMessage{" +
|
||||||
"address=" + address +
|
"address=" + address +
|
||||||
", challengerNonce=" + challengerNonce +
|
", challengerNonce=" + challengerNonce +
|
||||||
", neighbors=" + neighbors +
|
", neighborAddresses=" + neighborAddresses +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,22 @@ package io.bitsquare.p2p.routing.messages;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.routing.Neighbor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class NeighborsMessage implements AuthenticationMessage {
|
public final class NeighborsMessage implements AuthenticationMessage {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final HashMap<Address, Neighbor> neighbors;
|
public final ArrayList<Address> neighborAddresses;
|
||||||
|
|
||||||
public NeighborsMessage(HashMap<Address, Neighbor> neighbors) {
|
public NeighborsMessage(ArrayList<Address> neighborAddresses) {
|
||||||
this.neighbors = neighbors;
|
this.neighborAddresses = neighborAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NeighborsMessage{" + "neighbors=" + neighbors + '}';
|
return "NeighborsMessage{" + "neighborAddresses=" + neighborAddresses + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ public final class PingMessage implements MaintenanceMessage {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final int nonce;
|
public final long nonce;
|
||||||
|
|
||||||
public PingMessage(int nonce) {
|
public PingMessage(long nonce) {
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ public final class PongMessage implements MaintenanceMessage {
|
||||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final int nonce;
|
public final long nonce;
|
||||||
|
|
||||||
public PongMessage(int nonce) {
|
public PongMessage(long nonce) {
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ public final class RequestAuthenticationMessage implements AuthenticationMessage
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final Address address;
|
public final Address address;
|
||||||
public final int nonce;
|
public final long nonce;
|
||||||
|
|
||||||
public RequestAuthenticationMessage(Address address, int nonce) {
|
public RequestAuthenticationMessage(Address address, long nonce) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import io.bitsquare.storage.Storage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
@ -69,6 +70,7 @@ public class ProtectedExpirableDataStorage {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("Connection is not authenticated yet. We don't accept storage operations form non-authenticated nodes.");
|
log.warn("Connection is not authenticated yet. We don't accept storage operations form non-authenticated nodes.");
|
||||||
|
log.warn("Connection = " + connection);
|
||||||
connection.reportIllegalRequest(IllegalRequest.NotAuthenticated);
|
connection.reportIllegalRequest(IllegalRequest.NotAuthenticated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ public class ProtectedExpirableDataStorage {
|
||||||
this.authenticated = authenticated;
|
this.authenticated = authenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(ProtectedData protectedData, Address sender) {
|
public boolean add(ProtectedData protectedData, @Nullable Address sender) {
|
||||||
BigInteger hashOfPayload = getHashAsBigInteger(protectedData.expirablePayload);
|
BigInteger hashOfPayload = getHashAsBigInteger(protectedData.expirablePayload);
|
||||||
boolean containsKey = map.containsKey(hashOfPayload);
|
boolean containsKey = map.containsKey(hashOfPayload);
|
||||||
boolean result = checkPublicKeys(protectedData, true)
|
boolean result = checkPublicKeys(protectedData, true)
|
||||||
|
@ -119,9 +121,10 @@ public class ProtectedExpirableDataStorage {
|
||||||
log.trace("Data added to our map and it will be broadcasted to our neighbors.");
|
log.trace("Data added to our map and it will be broadcasted to our neighbors.");
|
||||||
UserThread.execute(() -> hashMapChangedListeners.stream().forEach(e -> e.onAdded(protectedData)));
|
UserThread.execute(() -> hashMapChangedListeners.stream().forEach(e -> e.onAdded(protectedData)));
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("\n\nSet after addProtectedExpirableData:\n");
|
StringBuilder sb = new StringBuilder("\n\n----------------------------------------------------\n" +
|
||||||
map.values().stream().forEach(e -> sb.append(e.toString() + "\n\n"));
|
"Data set after addProtectedExpirableData:");
|
||||||
sb.append("\n\n");
|
map.values().stream().forEach(e -> sb.append("\n\n").append(e.toString()));
|
||||||
|
sb.append("\n----------------------------------------------------\n\n");
|
||||||
log.trace(sb.toString());
|
log.trace(sb.toString());
|
||||||
|
|
||||||
if (!containsKey)
|
if (!containsKey)
|
||||||
|
@ -130,12 +133,12 @@ public class ProtectedExpirableDataStorage {
|
||||||
sequenceNumberMap.put(hashOfPayload, protectedData.sequenceNumber);
|
sequenceNumberMap.put(hashOfPayload, protectedData.sequenceNumber);
|
||||||
storage.queueUpForSave();
|
storage.queueUpForSave();
|
||||||
} else {
|
} else {
|
||||||
log.debug("add failed");
|
log.trace("add failed");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(ProtectedData protectedData, Address sender) {
|
public boolean remove(ProtectedData protectedData, @Nullable Address sender) {
|
||||||
BigInteger hashOfPayload = getHashAsBigInteger(protectedData.expirablePayload);
|
BigInteger hashOfPayload = getHashAsBigInteger(protectedData.expirablePayload);
|
||||||
boolean containsKey = map.containsKey(hashOfPayload);
|
boolean containsKey = map.containsKey(hashOfPayload);
|
||||||
if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data.");
|
if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data.");
|
||||||
|
@ -159,7 +162,7 @@ public class ProtectedExpirableDataStorage {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeMailboxData(ProtectedMailboxData protectedMailboxData, Address sender) {
|
public boolean removeMailboxData(ProtectedMailboxData protectedMailboxData, @Nullable Address sender) {
|
||||||
BigInteger hashOfData = getHashAsBigInteger(protectedMailboxData.expirablePayload);
|
BigInteger hashOfData = getHashAsBigInteger(protectedMailboxData.expirablePayload);
|
||||||
boolean containsKey = map.containsKey(hashOfData);
|
boolean containsKey = map.containsKey(hashOfData);
|
||||||
if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data.");
|
if (!containsKey) log.debug("Remove data ignored as we don't have an entry for that data.");
|
||||||
|
@ -245,7 +248,7 @@ public class ProtectedExpirableDataStorage {
|
||||||
int newSequenceNumber = data.sequenceNumber;
|
int newSequenceNumber = data.sequenceNumber;
|
||||||
Integer storedSequenceNumber = sequenceNumberMap.get(hashOfData);
|
Integer storedSequenceNumber = sequenceNumberMap.get(hashOfData);
|
||||||
if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber <= storedSequenceNumber) {
|
if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber <= storedSequenceNumber) {
|
||||||
log.warn("Sequence number is invalid. newSequenceNumber="
|
log.trace("Sequence number is invalid. newSequenceNumber="
|
||||||
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber);
|
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,7 +316,7 @@ public class ProtectedExpirableDataStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void broadcast(BroadcastMessage message, Address sender) {
|
private void broadcast(BroadcastMessage message, @Nullable Address sender) {
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
routing.broadcast(message, sender);
|
routing.broadcast(message, sender);
|
||||||
log.trace("Broadcast message " + message);
|
log.trace("Broadcast message " + message);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey;
|
import io.bitsquare.p2p.messaging.DecryptedMsgWithPubKey;
|
||||||
import io.bitsquare.p2p.messaging.MailboxMessage;
|
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -38,6 +39,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Security;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -50,10 +52,13 @@ public class EncryptionServiceTests {
|
||||||
|
|
||||||
private PubKeyRing pubKeyRing;
|
private PubKeyRing pubKeyRing;
|
||||||
private KeyRing keyRing;
|
private KeyRing keyRing;
|
||||||
private File dir = new File("/tmp/bitsquare_tests");
|
private File dir;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException {
|
public void setup() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
dir = File.createTempFile("temp_tests", "");
|
||||||
|
dir.delete();
|
||||||
dir.mkdir();
|
dir.mkdir();
|
||||||
KeyStorage keyStorage = new KeyStorage(dir);
|
KeyStorage keyStorage = new KeyStorage(dir);
|
||||||
keyRing = new KeyRing(keyStorage);
|
keyRing = new KeyRing(keyStorage);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import io.bitsquare.p2p.seed.SeedNode;
|
||||||
import io.bitsquare.p2p.storage.data.DataAndSeqNr;
|
import io.bitsquare.p2p.storage.data.DataAndSeqNr;
|
||||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||||
import io.bitsquare.p2p.storage.mocks.MockData;
|
import io.bitsquare.p2p.storage.mocks.MockData;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -40,16 +41,27 @@ public class P2PServiceTest {
|
||||||
private EncryptionService encryptionService1, encryptionService2, encryptionService3;
|
private EncryptionService encryptionService1, encryptionService2, encryptionService3;
|
||||||
private P2PService p2PService1, p2PService2, p2PService3;
|
private P2PService p2PService1, p2PService2, p2PService3;
|
||||||
private SeedNode seedNode1, seedNode2, seedNode3;
|
private SeedNode seedNode1, seedNode2, seedNode3;
|
||||||
|
private File dir1, dir2, dir3;
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws InterruptedException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException {
|
public void setup() throws InterruptedException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, CryptoException {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
dir1 = File.createTempFile("temp_tests1", "");
|
||||||
|
dir1.delete();
|
||||||
|
dir1.mkdir();
|
||||||
|
dir2 = File.createTempFile("temp_tests2", "");
|
||||||
|
dir2.delete();
|
||||||
|
dir2.mkdir();
|
||||||
|
dir3 = File.createTempFile("temp_tests3", "");
|
||||||
|
dir3.delete();
|
||||||
|
dir3.mkdir();
|
||||||
|
|
||||||
LocalhostNetworkNode.setSimulateTorDelayTorNode(10);
|
LocalhostNetworkNode.setSimulateTorDelayTorNode(10);
|
||||||
LocalhostNetworkNode.setSimulateTorDelayHiddenService(100);
|
LocalhostNetworkNode.setSimulateTorDelayHiddenService(100);
|
||||||
Routing.setMaxConnections(8);
|
Routing.setMaxConnections(8);
|
||||||
|
|
||||||
keyRing1 = new KeyRing(new KeyStorage(new File("temp_keyStorage1")));
|
keyRing1 = new KeyRing(new KeyStorage(dir1));
|
||||||
keyRing2 = new KeyRing(new KeyStorage(new File("temp_keyStorage2")));
|
keyRing2 = new KeyRing(new KeyStorage(dir2));
|
||||||
keyRing3 = new KeyRing(new KeyStorage(new File("temp_keyStorage3")));
|
keyRing3 = new KeyRing(new KeyStorage(dir3));
|
||||||
encryptionService1 = new EncryptionService(keyRing1);
|
encryptionService1 = new EncryptionService(keyRing1);
|
||||||
encryptionService2 = new EncryptionService(keyRing2);
|
encryptionService2 = new EncryptionService(keyRing2);
|
||||||
encryptionService3 = new EncryptionService(keyRing3);
|
encryptionService3 = new EncryptionService(keyRing3);
|
||||||
|
|
|
@ -2,12 +2,15 @@ package io.bitsquare.p2p.network;
|
||||||
|
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.routing.messages.RequestAuthenticationMessage;
|
import io.bitsquare.p2p.routing.messages.RequestAuthenticationMessage;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.Security;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
// TorNode created. Took 6 sec.
|
// TorNode created. Took 6 sec.
|
||||||
|
@ -17,6 +20,12 @@ import java.util.concurrent.CountDownLatch;
|
||||||
public class LocalhostNetworkNodeTest {
|
public class LocalhostNetworkNodeTest {
|
||||||
private static final Logger log = LoggerFactory.getLogger(LocalhostNetworkNodeTest.class);
|
private static final Logger log = LoggerFactory.getLogger(LocalhostNetworkNodeTest.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessage() throws InterruptedException, IOException {
|
public void testMessage() throws InterruptedException, IOException {
|
||||||
CountDownLatch msgLatch = new CountDownLatch(2);
|
CountDownLatch msgLatch = new CountDownLatch(2);
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import io.bitsquare.p2p.Message;
|
import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.mocks.MockMessage;
|
import io.bitsquare.p2p.mocks.MockMessage;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -12,6 +14,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.Security;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
// TorNode created. Took 6 sec.
|
// TorNode created. Took 6 sec.
|
||||||
|
@ -22,6 +25,11 @@ public class TorNetworkNodeTest {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TorNetworkNodeTest.class);
|
private static final Logger log = LoggerFactory.getLogger(TorNetworkNodeTest.class);
|
||||||
private CountDownLatch latch;
|
private CountDownLatch latch;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTorNodeBeforeSecondReady() throws InterruptedException, IOException {
|
public void testTorNodeBeforeSecondReady() throws InterruptedException, IOException {
|
||||||
latch = new CountDownLatch(1);
|
latch = new CountDownLatch(1);
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class RoutingTest {
|
||||||
P2PService p2PService1 = seedNode1.getP2PService();
|
P2PService p2PService1 = seedNode1.getP2PService();
|
||||||
latch.await();
|
latch.await();
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
Assert.assertEquals(0, p2PService1.getRouting().getAllNeighbors().size());
|
Assert.assertEquals(0, p2PService1.getRouting().getAllNeighborAddresses().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -180,8 +180,8 @@ public class RoutingTest {
|
||||||
});
|
});
|
||||||
P2PService p2PService2 = seedNode2.getP2PService();
|
P2PService p2PService2 = seedNode2.getP2PService();
|
||||||
latch.await();
|
latch.await();
|
||||||
Assert.assertEquals(1, p2PService1.getRouting().getAllNeighbors().size());
|
Assert.assertEquals(1, p2PService1.getRouting().getAllNeighborAddresses().size());
|
||||||
Assert.assertEquals(1, p2PService2.getRouting().getAllNeighbors().size());
|
Assert.assertEquals(1, p2PService2.getRouting().getAllNeighborAddresses().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
|
|
@ -15,6 +15,7 @@ import io.bitsquare.p2p.storage.data.ExpirableMailboxPayload;
|
||||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||||
import io.bitsquare.p2p.storage.data.ProtectedMailboxData;
|
import io.bitsquare.p2p.storage.data.ProtectedMailboxData;
|
||||||
import io.bitsquare.p2p.storage.mocks.MockData;
|
import io.bitsquare.p2p.storage.mocks.MockData;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -44,13 +45,24 @@ public class ProtectedDataStorageTest {
|
||||||
private KeyRing keyRing1, keyRing2;
|
private KeyRing keyRing1, keyRing2;
|
||||||
private MockData mockData;
|
private MockData mockData;
|
||||||
private int sleepTime = 100;
|
private int sleepTime = 100;
|
||||||
|
private File dir1;
|
||||||
|
private File dir2;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException {
|
public void setup() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
dir1 = File.createTempFile("temp_tests1", "");
|
||||||
|
dir1.delete();
|
||||||
|
dir1.mkdir();
|
||||||
|
dir2 = File.createTempFile("temp_tests2", "");
|
||||||
|
dir2.delete();
|
||||||
|
dir2.mkdir();
|
||||||
|
|
||||||
UserThread.executor = Executors.newSingleThreadExecutor();
|
UserThread.executor = Executors.newSingleThreadExecutor();
|
||||||
ProtectedExpirableDataStorage.CHECK_TTL_INTERVAL = 10 * 60 * 1000;
|
ProtectedExpirableDataStorage.CHECK_TTL_INTERVAL = 10 * 60 * 1000;
|
||||||
|
|
||||||
keyRing1 = new KeyRing(new KeyStorage(new File("temp_keyStorage1")));
|
keyRing1 = new KeyRing(new KeyStorage(dir1));
|
||||||
|
|
||||||
storageSignatureKeyPair1 = keyRing1.getSignatureKeyPair();
|
storageSignatureKeyPair1 = keyRing1.getSignatureKeyPair();
|
||||||
encryptionService1 = new EncryptionService(keyRing1);
|
encryptionService1 = new EncryptionService(keyRing1);
|
||||||
networkNode1 = TestUtils.getAndStartSeedNode(8001, encryptionService1, keyRing1, useClearNet, seedNodes).getP2PService().getNetworkNode();
|
networkNode1 = TestUtils.getAndStartSeedNode(8001, encryptionService1, keyRing1, useClearNet, seedNodes).getP2PService().getNetworkNode();
|
||||||
|
@ -58,7 +70,7 @@ public class ProtectedDataStorageTest {
|
||||||
dataStorage1 = new ProtectedExpirableDataStorage(routing1, new File("dummy"));
|
dataStorage1 = new ProtectedExpirableDataStorage(routing1, new File("dummy"));
|
||||||
|
|
||||||
// for mailbox
|
// for mailbox
|
||||||
keyRing2 = new KeyRing(new KeyStorage(new File("temp_keyStorage2")));
|
keyRing2 = new KeyRing(new KeyStorage(dir2));
|
||||||
storageSignatureKeyPair2 = keyRing2.getSignatureKeyPair();
|
storageSignatureKeyPair2 = keyRing2.getSignatureKeyPair();
|
||||||
encryptionService2 = new EncryptionService(keyRing2);
|
encryptionService2 = new EncryptionService(keyRing2);
|
||||||
|
|
||||||
|
@ -148,11 +160,18 @@ public class ProtectedDataStorageTest {
|
||||||
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
||||||
|
|
||||||
|
// add to empty map, any seq nr. -> ok
|
||||||
|
newSequenceNumber = 2;
|
||||||
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
|
ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
|
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// add with updated seq nr below previous -> failure
|
// add with updated seq nr below previous -> failure
|
||||||
newSequenceNumber = 1;
|
newSequenceNumber = 1;
|
||||||
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// add with updated seq nr over previous -> ok
|
// add with updated seq nr over previous -> ok
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue