Connections are now severed after a configurable time (12h by default) or when a limit is exceeded (150 by default)

This commit is contained in:
Christian Basler 2015-10-24 12:08:23 +02:00
parent a398b072b5
commit bdc8e025c1
5 changed files with 52 additions and 3 deletions

View File

@ -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.BROADCAST;
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG; import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
import static ch.dissem.bitmessage.utils.UnixTime.DAY; import static ch.dissem.bitmessage.utils.UnixTime.DAY;
import static ch.dissem.bitmessage.utils.UnixTime.HOUR;
/** /**
* <p>Use this class if you want to create a Bitmessage client.</p> * <p>Use this class if you want to create a Bitmessage client.</p>
@ -295,6 +296,8 @@ public class BitmessageContext {
Security security; Security security;
MessageCallback messageCallback; MessageCallback messageCallback;
Listener listener; Listener listener;
int connectionLimit = 150;
long connectionTTL = 12 * HOUR;
public Builder() { public Builder() {
} }
@ -349,6 +352,16 @@ public class BitmessageContext {
return this; 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() { public BitmessageContext build() {
nonNull("inventory", inventory); nonNull("inventory", inventory);
nonNull("nodeRegistry", nodeRegistry); nonNull("nodeRegistry", nodeRegistry);

View File

@ -56,6 +56,8 @@ public class InternalContext {
private final long clientNonce; private final long clientNonce;
private final long networkNonceTrialsPerByte = 1000; private final long networkNonceTrialsPerByte = 1000;
private final long networkExtraBytes = 1000; private final long networkExtraBytes = 1000;
private long connectionTTL;
private int connectionLimit;
public InternalContext(BitmessageContext.Builder builder) { public InternalContext(BitmessageContext.Builder builder) {
this.security = builder.security; this.security = builder.security;
@ -68,6 +70,8 @@ public class InternalContext {
this.clientNonce = security.randomNonce(); this.clientNonce = security.randomNonce();
this.messageCallback = builder.messageCallback; this.messageCallback = builder.messageCallback;
this.port = builder.port; this.port = builder.port;
this.connectionLimit = builder.connectionLimit;
this.connectionTTL = builder.connectionTTL;
Singleton.initialize(security); Singleton.initialize(security);
@ -166,7 +170,7 @@ public class InternalContext {
.payload(payload) .payload(payload)
.build(); .build();
if (object.isSigned()) { if (object.isSigned()) {
object.sign( from.getPrivateKey()); object.sign(from.getPrivateKey());
} }
if (payload instanceof Broadcast) { if (payload instanceof Broadcast) {
((Broadcast) payload).encrypt(); ((Broadcast) payload).encrypt();
@ -232,6 +236,14 @@ public class InternalContext {
return clientNonce; return clientNonce;
} }
public long getConnectionTTL() {
return connectionTTL;
}
public int getConnectionLimit() {
return connectionLimit;
}
public interface ContextHolder { public interface ContextHolder {
void setContext(InternalContext context); void setContext(InternalContext context);
} }

View File

@ -25,8 +25,12 @@ public class Singleton {
private static Security security; private static Security security;
public static void initialize(Security security) { public static void initialize(Security security) {
synchronized (Singleton.class) {
if (Singleton.security == null) {
Singleton.security = security; Singleton.security = security;
} }
}
}
public static Security security() { public static Security security() {
return security; return security;

View File

@ -51,8 +51,10 @@ import static ch.dissem.bitmessage.utils.UnixTime.MINUTE;
*/ */
public class Connection { public class Connection {
public static final int READ_TIMEOUT = 2000; 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 static final int CONNECT_TIMEOUT = 5000;
private final long startTime;
private final ConcurrentMap<InventoryVector, Long> ivCache; private final ConcurrentMap<InventoryVector, Long> ivCache;
private final InternalContext ctx; private final InternalContext ctx;
private final Mode mode; private final Mode mode;
@ -89,6 +91,7 @@ public class Connection {
private Connection(InternalContext context, Mode mode, MessageListener listener, Socket socket, private Connection(InternalContext context, Mode mode, MessageListener listener, Socket socket,
Map<InventoryVector, Long> requestedObjectsMap, NetworkAddress node, long syncTimeout) { Map<InventoryVector, Long> requestedObjectsMap, NetworkAddress node, long syncTimeout) {
this.startTime = UnixTime.now();
this.ctx = context; this.ctx = context;
this.mode = mode; this.mode = mode;
this.state = CONNECTING; this.state = CONNECTING;
@ -109,6 +112,10 @@ public class Connection {
timeoutInSeconds); timeoutInSeconds);
} }
public long getStartTime() {
return startTime;
}
public Mode getMode() { public Mode getMode() {
return mode; return mode;
} }

View File

@ -23,6 +23,7 @@ import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
import ch.dissem.bitmessage.ports.NetworkHandler; import ch.dissem.bitmessage.ports.NetworkHandler;
import ch.dissem.bitmessage.utils.Collections; import ch.dissem.bitmessage.utils.Collections;
import ch.dissem.bitmessage.utils.Property; import ch.dissem.bitmessage.utils.Property;
import ch.dissem.bitmessage.utils.UnixTime;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -112,9 +113,21 @@ public class DefaultNetworkHandler implements NetworkHandler, ContextHolder {
while (running) { while (running) {
try { try {
int active = 0; int active = 0;
long now = UnixTime.now();
synchronized (connections) { synchronized (connections) {
int diff = connections.size() - ctx.getConnectionLimit();
if (diff > 0) {
for (Connection c : connections) {
c.disconnect();
diff--;
if (diff == 0) break;
}
}
for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) { for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) {
Connection c = iterator.next(); Connection c = iterator.next();
if (now - c.getStartTime() > ctx.getConnectionTTL()) {
c.disconnect();
}
if (c.getState() == DISCONNECTED) { if (c.getState() == DISCONNECTED) {
// Remove the current element from the iterator and the list. // Remove the current element from the iterator and the list.
iterator.remove(); iterator.remove();