Refactor WIP

This commit is contained in:
Manfred Karrer 2015-12-23 18:19:01 +01:00
parent 6d68cf8470
commit e3cbaeef7e
11 changed files with 125 additions and 139 deletions

View File

@ -71,6 +71,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
private Address connectedSeedNode;
private volatile boolean shutDownInProgress;
private boolean shutDownComplete;
@SuppressWarnings("FieldCanBeLocal")
private MonadicBinding<Boolean> readyForAuthentication;
private final Storage<Address> dbStorage;
private Address myOnionAddress;

View File

@ -35,7 +35,6 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
protected final CopyOnWriteArraySet<SetupListener> setupListeners = new CopyOnWriteArraySet<>();
protected ListeningExecutorService executorService;
private Server server;
private ConnectionListener startServerConnectionListener;
private volatile boolean shutDownInProgress;
// accessed from different threads
@ -173,15 +172,11 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
final SettableFuture<Connection> resultFuture = SettableFuture.create();
Futures.addCallback(future, new FutureCallback<Connection>() {
public void onSuccess(Connection connection) {
UserThread.execute(() -> {
resultFuture.set(connection);
});
UserThread.execute(() -> resultFuture.set(connection));
}
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> {
resultFuture.setException(throwable);
});
UserThread.execute(() -> resultFuture.setException(throwable));
}
});
return resultFuture;
@ -305,7 +300,7 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
protected void startServer(ServerSocket serverSocket) {
Log.traceCall();
startServerConnectionListener = new ConnectionListener() {
ConnectionListener startServerConnectionListener = new ConnectionListener() {
@Override
public void onConnection(Connection connection) {
Log.traceCall("startServerConnectionListener connection=" + connection);

View File

@ -225,9 +225,7 @@ public class TorNetworkNode extends NetworkNode {
});
Futures.addCallback(future, new FutureCallback<TorNode<JavaOnionProxyManager, JavaOnionProxyContext>>() {
public void onSuccess(TorNode<JavaOnionProxyManager, JavaOnionProxyContext> torNode) {
UserThread.execute(() -> {
resultHandler.accept(torNode);
});
UserThread.execute(() -> resultHandler.accept(torNode));
}
public void onFailure(@NotNull Throwable throwable) {

View File

@ -16,13 +16,11 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkArgument;
// authentication protocol:
// node2 -> node1 AuthenticationRequest
// node1: close connection
@ -40,9 +38,9 @@ public class AuthenticationHandshake implements MessageListener {
private final Address myAddress;
private final Address peerAddress;
private SettableFuture<Connection> resultFuture;
private long startAuthTs;
private long nonce = 0;
private final long startAuthTs;
private Optional<SettableFuture<Connection>> resultFutureOptional = Optional.empty();
private long nonce;
private boolean stopped;
@ -57,22 +55,29 @@ public class AuthenticationHandshake implements MessageListener {
this.myAddress = myAddress;
this.peerAddress = peerAddress;
networkNode.addMessageListener(this);
resultFuture = SettableFuture.create();
startAuthTs = System.currentTimeMillis();
stopped = false;
nonce = 0;
networkNode.addMessageListener(this);
}
///////////////////////////////////////////////////////////////////////////////////////////
// MessageListener implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onMessage(Message message, Connection connection) {
if (stopped) {
log.warn("AuthenticationHandshake already shut down but still got onMessage called. That must not happen.");
return;
}
if (message instanceof AuthenticationMessage) {
// We are listening on all connections, so we need to filter out only our peer address
// We are listening on all connections, so we need to filter out only our peer
if (((AuthenticationMessage) message).address.equals(peerAddress)) {
Log.traceCall(message.toString());
checkArgument(!stopped);
if (message instanceof AuthenticationResponse) {
// Requesting peer
// We use the active connectionType if we started the authentication request to another peer
@ -173,6 +178,11 @@ public class AuthenticationHandshake implements MessageListener {
Log.traceCall("peerAddress " + peerAddress);
// Requesting peer
if (stopped) {
log.warn("AuthenticationHandshake already shut down but still got requestAuthentication called. That must not happen.");
}
resultFutureOptional = Optional.of(SettableFuture.create());
AuthenticationRequest authenticationRequest = new AuthenticationRequest(myAddress, getAndSetNonce());
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, authenticationRequest);
Futures.addCallback(future, new FutureCallback<Connection>() {
@ -193,7 +203,7 @@ public class AuthenticationHandshake implements MessageListener {
}
});
return resultFuture;
return resultFutureOptional.get();
}
@ -206,6 +216,12 @@ public class AuthenticationHandshake implements MessageListener {
Log.traceCall("peerAddress " + peerAddress);
// Responding peer
if (stopped) {
log.warn("AuthenticationHandshake already shut down but still got respondToAuthenticationRequest called. That must not happen.");
}
resultFutureOptional = Optional.of(SettableFuture.create());
log.trace("AuthenticationRequest from " + peerAddress + " at " + myAddress);
log.info("We shut down inbound connection from peer {} to establish a new " +
"connection with his reported address.", peerAddress);
@ -223,7 +239,7 @@ public class AuthenticationHandshake implements MessageListener {
SettableFuture<Connection> future = networkNode.sendMessage(peerAddress, authenticationResponse);
Futures.addCallback(future, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
public void onSuccess(Connection connection) {
log.trace("onSuccess sending AuthenticationResponse");
connection.setPeerAddress(peerAddress);
@ -241,7 +257,7 @@ public class AuthenticationHandshake implements MessageListener {
}
}, 200, TimeUnit.MILLISECONDS);
});
return resultFuture;
return resultFutureOptional.get();
}
@ -262,7 +278,7 @@ public class AuthenticationHandshake implements MessageListener {
Log.traceCall();
nonce = new Random().nextLong();
while (nonce == 0)
nonce = getAndSetNonce();
nonce = new Random().nextLong();
return nonce;
}
@ -270,19 +286,25 @@ public class AuthenticationHandshake implements MessageListener {
private void failed(@NotNull Throwable throwable) {
Log.traceCall();
shutDown();
resultFuture.setException(throwable);
if (resultFutureOptional.isPresent())
resultFutureOptional.get().setException(throwable);
else
log.warn("failed called but resultFuture = null. That must never happen.");
}
private void completed(Connection connection) {
Log.traceCall();
shutDown();
resultFuture.set(connection);
if (resultFutureOptional.isPresent())
resultFutureOptional.get().set(connection);
else
log.warn("completed called but resultFuture = null. That must never happen.");
}
private void shutDown() {
Log.traceCall();
networkNode.removeMessageListener(this);
stopped = true;
networkNode.removeMessageListener(this);
}
@Override

View File

@ -26,8 +26,8 @@ public class MaintenanceManager implements MessageListener {
private static final Logger log = LoggerFactory.getLogger(MaintenanceManager.class);
private Timer sendPingTimer;
private PeerGroup peerGroup;
private NetworkNode networkNode;
private final PeerGroup peerGroup;
private final NetworkNode networkNode;
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -12,7 +12,7 @@ public class Peer {
public final Connection connection;
public final Address address;
private long pingNonce;
private final long pingNonce;
public Peer(Connection connection) {
this.connection = connection;

View File

@ -27,18 +27,24 @@ import static com.google.common.base.Preconditions.checkArgument;
public class PeerGroup implements MessageListener, ConnectionListener {
private static final Logger log = LoggerFactory.getLogger(PeerGroup.class);
static int simulateAuthTorNode = 0;
private static int simulateAuthTorNode = 0;
public static void setSimulateAuthTorNode(int simulateAuthTorNode) {
PeerGroup.simulateAuthTorNode = simulateAuthTorNode;
}
static int MAX_CONNECTIONS_LOW_PRIO = 8;
static int MAX_CONNECTIONS_NORMAL_PRIO = MAX_CONNECTIONS_LOW_PRIO + 4;
static int MAX_CONNECTIONS_HIGH_PRIO = MAX_CONNECTIONS_NORMAL_PRIO + 4;
private static int MAX_CONNECTIONS_LOW_PRIORITY;
private static int MAX_CONNECTIONS_NORMAL_PRIORITY;
private static int MAX_CONNECTIONS_HIGH_PRIORITY;
public static void setMaxConnectionsLowPrio(int maxConnectionsLowPrio) {
MAX_CONNECTIONS_LOW_PRIO = maxConnectionsLowPrio;
public static void setMaxConnectionsLowPriority(int maxConnectionsLowPriority) {
MAX_CONNECTIONS_LOW_PRIORITY = maxConnectionsLowPriority;
MAX_CONNECTIONS_NORMAL_PRIORITY = MAX_CONNECTIONS_LOW_PRIORITY + 4;
MAX_CONNECTIONS_HIGH_PRIORITY = MAX_CONNECTIONS_NORMAL_PRIORITY + 4;
}
static {
setMaxConnectionsLowPriority(8);
}
static final int INACTIVITY_PERIOD_BEFORE_PING = 30 * 1000;
@ -106,7 +112,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
if (message instanceof AuthenticationRequest)
processAuthenticationRequest((AuthenticationRequest) message, connection);
else if (message instanceof AuthenticationRejection)
processAuthenticationRejection((AuthenticationRejection) message, connection);
processAuthenticationRejection((AuthenticationRejection) message);
}
@ -120,26 +126,24 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info("Broadcast message to {} peers. Message: {}", authenticatedPeers.values().size(), message);
authenticatedPeers.values().stream()
.filter(e -> !e.address.equals(sender))
.forEach(peer -> {
UserThread.runAfterRandomDelay(() -> {
final Address address = peer.address;
log.trace("Broadcast message from " + getMyAddress() + " to " + address + ".");
SettableFuture<Connection> future = networkNode.sendMessage(address, message);
Futures.addCallback(future, new FutureCallback<Connection>() {
@Override
public void onSuccess(Connection connection) {
log.trace("Broadcast from " + getMyAddress() + " to " + address + " succeeded.");
}
.forEach(peer -> UserThread.runAfterRandomDelay(() -> {
final Address address = peer.address;
log.trace("Broadcast message from " + getMyAddress() + " to " + address + ".");
SettableFuture<Connection> future = networkNode.sendMessage(address, message);
Futures.addCallback(future, new FutureCallback<Connection>() {
@Override
public void onSuccess(Connection connection) {
log.trace("Broadcast from " + getMyAddress() + " to " + address + " succeeded.");
}
@Override
public void onFailure(@NotNull Throwable throwable) {
log.info("Broadcast failed. " + throwable.getMessage());
UserThread.execute(() -> removePeer(address));
}
});
},
10, 200, TimeUnit.MILLISECONDS);
});
@Override
public void onFailure(@NotNull Throwable throwable) {
log.info("Broadcast failed. " + throwable.getMessage());
UserThread.execute(() -> removePeer(address));
}
});
},
10, 200, TimeUnit.MILLISECONDS));
} else {
log.info("Message not broadcasted because we have no authenticated peers yet. " +
"message = {}", message);
@ -158,7 +162,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
///////////////////////////////////////////////////////////////////////////////////////////
// Process incoming authentication request
// Process incoming authentication messages
///////////////////////////////////////////////////////////////////////////////////////////
private void processAuthenticationRequest(AuthenticationRequest message, final Connection connection) {
@ -201,7 +205,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
}
}
private void processAuthenticationRejection(AuthenticationRejection message, final Connection connection) {
private void processAuthenticationRejection(AuthenticationRejection message) {
Log.traceCall(message.toString());
Address peerAddress = message.address;
cancelOwnAuthenticationRequest(peerAddress, authenticationHandshakes.get(peerAddress));
@ -212,15 +216,10 @@ public class PeerGroup implements MessageListener, ConnectionListener {
SettableFuture<Connection> future = authenticationHandshake.respondToAuthenticationRequest(message, connection);
Futures.addCallback(future, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
if (connection != null) {
checkArgument(peerAddress.equals(connection.getPeerAddress()), "peerAddress does not match connection.getPeerAddress()");
log.info("We got the peer who did an authentication request authenticated.");
addAuthenticatedPeer(connection, peerAddress);
} else {
log.error("Connection is null. That must not happen.");
removePeer(peerAddress);
}
public void onSuccess(Connection connection) {
checkArgument(peerAddress.equals(connection.getPeerAddress()), "peerAddress does not match connection.getPeerAddress()");
log.info("We got the peer who did an authentication request authenticated.");
addAuthenticatedPeer(connection, peerAddress);
}
@Override
@ -229,7 +228,9 @@ public class PeerGroup implements MessageListener, ConnectionListener {
"That can happen if the peer went offline. " + throwable.getMessage());
removePeer(peerAddress);
}
});
}
);
}
private void cancelOwnAuthenticationRequest(Address peerAddress, AuthenticationHandshake authenticationHandshake) {
@ -264,24 +265,16 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info("We try to authenticate to seed node {}.", peerAddress);
authenticate(peerAddress, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
if (connection != null) {
log.info("We got our first seed node authenticated. " +
"We try if there are reported peers available to authenticate.");
public void onSuccess(Connection connection) {
log.info("We got our first seed node authenticated. " +
"We try if there are reported peers available to authenticate.");
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingReportedPeer();
} else {
log.warn("Connection is null. That should never happen. " + peerAddress);
removePeer(peerAddress);
log.info("We try another random seed node for first authentication attempt.");
authenticateToFirstSeedNode(getAndRemoveRandomAddress(remainingSeedNodes));
}
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingReportedPeer();
}
@Override
public void onFailure(Throwable throwable) {
public void onFailure(@NotNull Throwable throwable) {
log.info("Authentication to " + peerAddress + " failed." +
"\nThat is expected if seed nodes are offline." +
"\nException:" + throwable.getMessage());
@ -310,24 +303,16 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info("We try to authenticate to seed node {}.", peerAddress);
authenticate(peerAddress, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
if (connection != null) {
log.info("We got a seed node authenticated. " +
"We try if there are more seed nodes available to authenticate.");
public void onSuccess(Connection connection) {
log.info("We got a seed node authenticated. " +
"We try if there are more seed nodes available to authenticate.");
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingSeedNode();
} else {
log.warn("Connection is null. That should never happen. " + peerAddress);
removePeer(peerAddress);
log.info("We try another random seed node for authentication.");
authenticateToRemainingSeedNode();
}
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingSeedNode();
}
@Override
public void onFailure(Throwable throwable) {
public void onFailure(@NotNull Throwable throwable) {
log.info("Authentication to " + peerAddress + " failed." +
"\nThat is expected if the seed node is offline." +
"\nException:" + throwable.getMessage());
@ -367,24 +352,16 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info("We try to authenticate to peer {}.", peerAddress);
authenticate(peerAddress, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
if (connection != null) {
log.info("We got a peer authenticated. " +
"We try if there are more reported peers available to authenticate.");
public void onSuccess(Connection connection) {
log.info("We got a peer authenticated. " +
"We try if there are more reported peers available to authenticate.");
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingReportedPeer();
} else {
log.warn("Connection is null. That should never happen. " + peerAddress);
removePeer(peerAddress);
log.info("We try another random seed node for authentication.");
authenticateToRemainingReportedPeer();
}
addAuthenticatedPeer(connection, peerAddress);
authenticateToRemainingReportedPeer();
}
@Override
public void onFailure(Throwable throwable) {
public void onFailure(@NotNull Throwable throwable) {
log.info("Authentication to " + peerAddress + " failed." +
"\nThat is expected if the peer is offline." +
"\nException:" + throwable.getMessage());
@ -425,23 +402,16 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info("We try to authenticate to peer {} for sending a private message.", peerAddress);
authenticate(peerAddress, new FutureCallback<Connection>() {
@Override
public void onSuccess(@Nullable Connection connection) {
if (connection != null) {
log.info("We got a new peer for sending a private message authenticated.");
public void onSuccess(Connection connection) {
log.info("We got a new peer for sending a private message authenticated.");
addAuthenticatedPeer(connection, peerAddress);
if (completeHandler != null)
completeHandler.run();
} else {
log.error("Connection is null. That should never happen. " + peerAddress);
removePeer(peerAddress);
if (faultHandler != null)
faultHandler.run();
}
addAuthenticatedPeer(connection, peerAddress);
if (completeHandler != null)
completeHandler.run();
}
@Override
public void onFailure(Throwable throwable) {
public void onFailure(@NotNull Throwable throwable) {
log.error("Authentication to " + peerAddress + " for sending a private message failed." +
"\nSeems that the peer is offline." +
"\nException:" + throwable.getMessage());
@ -512,7 +482,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
}
private boolean maxConnectionsForAuthReached() {
return authenticatedPeers.size() >= MAX_CONNECTIONS_LOW_PRIO;
return authenticatedPeers.size() >= MAX_CONNECTIONS_LOW_PRIORITY;
}
private boolean remainingSeedNodesAvailable() {
@ -526,7 +496,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
private boolean checkIfConnectedPeersExceeds() {
Log.traceCall();
int size = authenticatedPeers.size();
if (size > PeerGroup.MAX_CONNECTIONS_LOW_PRIO) {
if (size > PeerGroup.MAX_CONNECTIONS_LOW_PRIORITY) {
Set<Connection> allConnections = networkNode.getAllConnections();
int allConnectionsSize = allConnections.size();
log.info("We have {} connections open. Lets remove the passive connections" +
@ -541,8 +511,8 @@ public class PeerGroup implements MessageListener, ConnectionListener {
if (authenticatedConnections.size() == 0) {
log.debug("There are no passive connections for closing. We check if we are exceeding " +
"MAX_CONNECTIONS_NORMAL ({}) ", PeerGroup.MAX_CONNECTIONS_NORMAL_PRIO);
if (size > PeerGroup.MAX_CONNECTIONS_NORMAL_PRIO) {
"MAX_CONNECTIONS_NORMAL ({}) ", PeerGroup.MAX_CONNECTIONS_NORMAL_PRIORITY);
if (size > PeerGroup.MAX_CONNECTIONS_NORMAL_PRIORITY) {
authenticatedConnections = allConnections.stream()
.filter(e -> e.isAuthenticated())
.filter(e -> e.getConnectionPriority() == ConnectionPriority.PASSIVE || e.getConnectionPriority() == ConnectionPriority.ACTIVE)
@ -550,8 +520,8 @@ public class PeerGroup implements MessageListener, ConnectionListener {
if (authenticatedConnections.size() == 0) {
log.debug("There are no passive or active connections for closing. We check if we are exceeding " +
"MAX_CONNECTIONS_HIGH ({}) ", PeerGroup.MAX_CONNECTIONS_HIGH_PRIO);
if (size > PeerGroup.MAX_CONNECTIONS_HIGH_PRIO) {
"MAX_CONNECTIONS_HIGH ({}) ", PeerGroup.MAX_CONNECTIONS_HIGH_PRIORITY);
if (size > PeerGroup.MAX_CONNECTIONS_HIGH_PRIORITY) {
authenticatedConnections = allConnections.stream()
.filter(e -> e.isAuthenticated())
.collect(Collectors.toList());
@ -604,7 +574,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
// we disconnect misbehaving nodes trying to send too many peers
// reported peers include the authenticated peers which is normally max. 8 but we give some headroom
// for safety
if (reportedPeersToAdd.size() > (MAX_REPORTED_PEERS + MAX_CONNECTIONS_LOW_PRIO * 3)) {
if (reportedPeersToAdd.size() > (MAX_REPORTED_PEERS + MAX_CONNECTIONS_LOW_PRIORITY * 3)) {
connection.shutDown();
} else {
// In case we have one of the peers already we adjust the lastActivityDate by adjusting the date to the mid
@ -681,7 +651,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
printReportedPeers();
}
public void printAuthenticatedPeers() {
private void printAuthenticatedPeers() {
StringBuilder result = new StringBuilder("\n\n------------------------------------------------------------\n" +
"Authenticated peers for node " + getMyAddress() + ":");
authenticatedPeers.values().stream().forEach(e -> result.append("\n").append(e.address));
@ -689,7 +659,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
log.info(result.toString());
}
public void printReportedPeers() {
private void printReportedPeers() {
StringBuilder result = new StringBuilder("\n\n------------------------------------------------------------\n" +
"Reported peers for node " + getMyAddress() + ":");
reportedPeers.stream().forEach(e -> result.append("\n").append(e));

View File

@ -63,10 +63,10 @@ public class SeedNode {
String arg2 = args[2];
int maxConnections = Integer.parseInt(arg2);
checkArgument(maxConnections < 1000, "maxConnections seems to be a bit too high...");
PeerGroup.setMaxConnectionsLowPrio(maxConnections);
PeerGroup.setMaxConnectionsLowPriority(maxConnections);
} else {
// we keep default a higher connection size for seed nodes
PeerGroup.setMaxConnectionsLowPrio(50);
PeerGroup.setMaxConnectionsLowPriority(50);
}
if (args.length > 3) {
String arg3 = args[3];

View File

@ -65,7 +65,7 @@ public class P2PDataStorage implements MessageListener {
private void init() {
Log.traceCall();
HashMap<ByteArray, Integer> persisted = storage.initAndGetPersisted("SequenceNumberMap");
if (persisted != null)
if (persisted != null)
sequenceNumberMap = persisted;
timer.scheduleAtFixedRate(new TimerTask() {
@ -171,7 +171,7 @@ public class P2PDataStorage implements MessageListener {
map.put(hashOfPayload, protectedData);
sequenceNumberMap.put(hashOfPayload, protectedData.sequenceNumber);
storage.queueUpForSave(sequenceNumberMap);
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
sb.append("Data set after addProtectedExpirableData:");
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()).append("\n"));

View File

@ -59,7 +59,7 @@ public class P2PServiceTest {
LocalhostNetworkNode.setSimulateTorDelayTorNode(10);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(100);
PeerGroup.setMaxConnectionsLowPrio(8);
PeerGroup.setMaxConnectionsLowPriority(8);
keyRing1 = new KeyRing(new KeyStorage(dir1));
keyRing2 = new KeyRing(new KeyStorage(dir2));

View File

@ -33,7 +33,7 @@ public class PeerGroupTest {
public void setup() throws InterruptedException {
LocalhostNetworkNode.setSimulateTorDelayTorNode(50);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(8);
PeerGroup.setMaxConnectionsLowPrio(100);
PeerGroup.setMaxConnectionsLowPriority(100);
seedNodes = new HashSet<>();
if (useLocalhost) {