diff --git a/domain/src/main/java/ch/dissem/bitmessage/BitmessageContext.java b/domain/src/main/java/ch/dissem/bitmessage/BitmessageContext.java index d7d8980..1e4e905 100644 --- a/domain/src/main/java/ch/dissem/bitmessage/BitmessageContext.java +++ b/domain/src/main/java/ch/dissem/bitmessage/BitmessageContext.java @@ -40,6 +40,7 @@ import static ch.dissem.bitmessage.entity.Plaintext.Status.*; import static ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST; import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG; import static ch.dissem.bitmessage.utils.UnixTime.DAY; +import static ch.dissem.bitmessage.utils.UnixTime.HOUR; /** *

Use this class if you want to create a Bitmessage client.

@@ -295,6 +296,8 @@ public class BitmessageContext { Security security; MessageCallback messageCallback; Listener listener; + int connectionLimit = 150; + long connectionTTL = 12 * HOUR; public Builder() { } @@ -349,6 +352,16 @@ public class BitmessageContext { return this; } + public Builder connectionLimit(int connectionLimit) { + this.connectionLimit = connectionLimit; + return this; + } + + public Builder connectionTTL(int hours) { + this.connectionTTL = hours * HOUR; + return this; + } + public BitmessageContext build() { nonNull("inventory", inventory); nonNull("nodeRegistry", nodeRegistry); diff --git a/domain/src/main/java/ch/dissem/bitmessage/InternalContext.java b/domain/src/main/java/ch/dissem/bitmessage/InternalContext.java index 6d969bd..bbdedb6 100644 --- a/domain/src/main/java/ch/dissem/bitmessage/InternalContext.java +++ b/domain/src/main/java/ch/dissem/bitmessage/InternalContext.java @@ -56,6 +56,8 @@ public class InternalContext { private final long clientNonce; private final long networkNonceTrialsPerByte = 1000; private final long networkExtraBytes = 1000; + private long connectionTTL; + private int connectionLimit; public InternalContext(BitmessageContext.Builder builder) { this.security = builder.security; @@ -68,6 +70,8 @@ public class InternalContext { this.clientNonce = security.randomNonce(); this.messageCallback = builder.messageCallback; this.port = builder.port; + this.connectionLimit = builder.connectionLimit; + this.connectionTTL = builder.connectionTTL; Singleton.initialize(security); @@ -166,7 +170,7 @@ public class InternalContext { .payload(payload) .build(); if (object.isSigned()) { - object.sign( from.getPrivateKey()); + object.sign(from.getPrivateKey()); } if (payload instanceof Broadcast) { ((Broadcast) payload).encrypt(); @@ -232,6 +236,14 @@ public class InternalContext { return clientNonce; } + public long getConnectionTTL() { + return connectionTTL; + } + + public int getConnectionLimit() { + return connectionLimit; + } + public interface ContextHolder { void setContext(InternalContext context); } diff --git a/domain/src/main/java/ch/dissem/bitmessage/utils/Singleton.java b/domain/src/main/java/ch/dissem/bitmessage/utils/Singleton.java index 169db77..d272beb 100644 --- a/domain/src/main/java/ch/dissem/bitmessage/utils/Singleton.java +++ b/domain/src/main/java/ch/dissem/bitmessage/utils/Singleton.java @@ -25,7 +25,11 @@ public class Singleton { private static Security security; public static void initialize(Security security) { - Singleton.security = security; + synchronized (Singleton.class) { + if (Singleton.security == null) { + Singleton.security = security; + } + } } public static Security security() { diff --git a/networking/src/main/java/ch/dissem/bitmessage/networking/Connection.java b/networking/src/main/java/ch/dissem/bitmessage/networking/Connection.java index 6312557..f0ff5ed 100644 --- a/networking/src/main/java/ch/dissem/bitmessage/networking/Connection.java +++ b/networking/src/main/java/ch/dissem/bitmessage/networking/Connection.java @@ -51,8 +51,10 @@ import static ch.dissem.bitmessage.utils.UnixTime.MINUTE; */ public class Connection { public static final int READ_TIMEOUT = 2000; - private final static Logger LOG = LoggerFactory.getLogger(Connection.class); + private static final Logger LOG = LoggerFactory.getLogger(Connection.class); private static final int CONNECT_TIMEOUT = 5000; + + private final long startTime; private final ConcurrentMap ivCache; private final InternalContext ctx; private final Mode mode; @@ -89,6 +91,7 @@ public class Connection { private Connection(InternalContext context, Mode mode, MessageListener listener, Socket socket, Map requestedObjectsMap, NetworkAddress node, long syncTimeout) { + this.startTime = UnixTime.now(); this.ctx = context; this.mode = mode; this.state = CONNECTING; @@ -109,6 +112,10 @@ public class Connection { timeoutInSeconds); } + public long getStartTime() { + return startTime; + } + public Mode getMode() { return mode; } diff --git a/networking/src/main/java/ch/dissem/bitmessage/networking/DefaultNetworkHandler.java b/networking/src/main/java/ch/dissem/bitmessage/networking/DefaultNetworkHandler.java index e563152..7b49978 100644 --- a/networking/src/main/java/ch/dissem/bitmessage/networking/DefaultNetworkHandler.java +++ b/networking/src/main/java/ch/dissem/bitmessage/networking/DefaultNetworkHandler.java @@ -23,6 +23,7 @@ import ch.dissem.bitmessage.entity.valueobject.NetworkAddress; import ch.dissem.bitmessage.ports.NetworkHandler; import ch.dissem.bitmessage.utils.Collections; import ch.dissem.bitmessage.utils.Property; +import ch.dissem.bitmessage.utils.UnixTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -112,9 +113,21 @@ public class DefaultNetworkHandler implements NetworkHandler, ContextHolder { while (running) { try { int active = 0; + long now = UnixTime.now(); synchronized (connections) { + int diff = connections.size() - ctx.getConnectionLimit(); + if (diff > 0) { + for (Connection c : connections) { + c.disconnect(); + diff--; + if (diff == 0) break; + } + } for (Iterator iterator = connections.iterator(); iterator.hasNext(); ) { Connection c = iterator.next(); + if (now - c.getStartTime() > ctx.getConnectionTTL()) { + c.disconnect(); + } if (c.getState() == DISCONNECTED) { // Remove the current element from the iterator and the list. iterator.remove();