mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 11:49:04 +01:00
Accept connections asynchronously.
This commit is contained in:
@@ -8,7 +8,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -51,24 +50,22 @@ class PluginManagerImpl implements PluginManager {
|
||||
"net.sf.briar.plugins.socket.SimpleSocketPluginFactory"
|
||||
};
|
||||
|
||||
private static final int THREAD_POOL_SIZE = 5;
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Executor executor;
|
||||
private final Poller poller;
|
||||
private final ConnectionDispatcher dispatcher;
|
||||
private final UiCallback uiCallback;
|
||||
private final Executor executor;
|
||||
private final List<BatchPlugin> batchPlugins;
|
||||
private final List<StreamPlugin> streamPlugins;
|
||||
|
||||
@Inject
|
||||
PluginManagerImpl(DatabaseComponent db, Poller poller,
|
||||
PluginManagerImpl(DatabaseComponent db, Executor executor, Poller poller,
|
||||
ConnectionDispatcher dispatcher, UiCallback uiCallback) {
|
||||
this.db = db;
|
||||
this.executor = executor;
|
||||
this.poller = poller;
|
||||
this.dispatcher = dispatcher;
|
||||
this.uiCallback = uiCallback;
|
||||
executor = new ScheduledThreadPoolExecutor(THREAD_POOL_SIZE);
|
||||
batchPlugins = new ArrayList<BatchPlugin>();
|
||||
streamPlugins = new ArrayList<StreamPlugin>();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.sf.briar.api.transport.BatchTransportWriter;
|
||||
import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionDispatcher;
|
||||
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||
import net.sf.briar.api.transport.ConnectionRecogniser.Callback;
|
||||
import net.sf.briar.api.transport.StreamConnectionFactory;
|
||||
import net.sf.briar.api.transport.StreamTransportConnection;
|
||||
import net.sf.briar.api.transport.TransportConstants;
|
||||
@@ -39,9 +40,9 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
|
||||
this.streamConnFactory = streamConnFactory;
|
||||
}
|
||||
|
||||
public void dispatchReader(TransportId t, BatchTransportReader r) {
|
||||
public void dispatchReader(TransportId t, final BatchTransportReader r) {
|
||||
// Read the encrypted IV
|
||||
byte[] encryptedIv;
|
||||
final byte[] encryptedIv;
|
||||
try {
|
||||
encryptedIv = readIv(r.getInputStream());
|
||||
} catch(IOException e) {
|
||||
@@ -49,20 +50,22 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
|
||||
r.dispose(false);
|
||||
return;
|
||||
}
|
||||
// Get the connection context, or null if the IV wasn't expected
|
||||
ConnectionContext ctx;
|
||||
try {
|
||||
ctx = recogniser.acceptConnection(t, encryptedIv);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
||||
r.dispose(false);
|
||||
return;
|
||||
}
|
||||
if(ctx == null) {
|
||||
r.dispose(false);
|
||||
return;
|
||||
}
|
||||
batchConnFactory.createIncomingConnection(ctx, r, encryptedIv);
|
||||
// Get the connection context asynchronously
|
||||
recogniser.acceptConnection(t, encryptedIv, new Callback() {
|
||||
|
||||
public void connectionAccepted(ConnectionContext ctx) {
|
||||
batchConnFactory.createIncomingConnection(ctx, r, encryptedIv);
|
||||
}
|
||||
|
||||
public void connectionRejected() {
|
||||
r.dispose(false);
|
||||
}
|
||||
|
||||
public void handleException(DbException e) {
|
||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
||||
r.dispose(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private byte[] readIv(InputStream in) throws IOException {
|
||||
@@ -82,9 +85,9 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
|
||||
}
|
||||
|
||||
public void dispatchIncomingConnection(TransportId t,
|
||||
StreamTransportConnection s) {
|
||||
final StreamTransportConnection s) {
|
||||
// Read the encrypted IV
|
||||
byte[] encryptedIv;
|
||||
final byte[] encryptedIv;
|
||||
try {
|
||||
encryptedIv = readIv(s.getInputStream());
|
||||
} catch(IOException e) {
|
||||
@@ -92,20 +95,22 @@ public class ConnectionDispatcherImpl implements ConnectionDispatcher {
|
||||
s.dispose(false);
|
||||
return;
|
||||
}
|
||||
// Get the connection context, or null if the IV wasn't expected
|
||||
ConnectionContext ctx;
|
||||
try {
|
||||
ctx = recogniser.acceptConnection(t, encryptedIv);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
||||
s.dispose(false);
|
||||
return;
|
||||
}
|
||||
if(ctx == null) {
|
||||
s.dispose(false);
|
||||
return;
|
||||
}
|
||||
streamConnFactory.createIncomingConnection(ctx, s, encryptedIv);
|
||||
// Get the connection context asynchronously
|
||||
recogniser.acceptConnection(t, encryptedIv, new Callback() {
|
||||
|
||||
public void connectionAccepted(ConnectionContext ctx) {
|
||||
streamConnFactory.createIncomingConnection(ctx, s, encryptedIv);
|
||||
}
|
||||
|
||||
public void connectionRejected() {
|
||||
s.dispose(false);
|
||||
}
|
||||
|
||||
public void handleException(DbException e) {
|
||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
||||
s.dispose(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void dispatchOutgoingConnection(ContactId c, TransportIndex i,
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -31,7 +32,6 @@ import net.sf.briar.api.db.event.TransportAddedEvent;
|
||||
import net.sf.briar.api.protocol.Transport;
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
import net.sf.briar.api.protocol.TransportIndex;
|
||||
import net.sf.briar.api.transport.ConnectionContext;
|
||||
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||
import net.sf.briar.api.transport.ConnectionWindow;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
@@ -46,6 +46,7 @@ DatabaseListener {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final DatabaseComponent db;
|
||||
private final Executor executor;
|
||||
private final Cipher ivCipher;
|
||||
private final Map<Bytes, Context> expected;
|
||||
private final Collection<TransportId> localTransportIds;
|
||||
@@ -53,9 +54,11 @@ DatabaseListener {
|
||||
private boolean initialised = false;
|
||||
|
||||
@Inject
|
||||
ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db) {
|
||||
ConnectionRecogniserImpl(CryptoComponent crypto, DatabaseComponent db,
|
||||
Executor executor) {
|
||||
this.crypto = crypto;
|
||||
this.db = db;
|
||||
this.executor = executor;
|
||||
ivCipher = crypto.getIvCipher();
|
||||
expected = new HashMap<Bytes, Context>();
|
||||
localTransportIds = new ArrayList<TransportId>();
|
||||
@@ -63,6 +66,12 @@ DatabaseListener {
|
||||
}
|
||||
|
||||
private synchronized void initialise() throws DbException {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
eraseSecrets();
|
||||
}
|
||||
});
|
||||
for(Transport t : db.getLocalTransports()) {
|
||||
localTransportIds.add(t.getId());
|
||||
}
|
||||
@@ -73,12 +82,6 @@ DatabaseListener {
|
||||
// The contact was removed - clean up in eventOccurred()
|
||||
}
|
||||
}
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
eraseSecrets();
|
||||
}
|
||||
});
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
@@ -125,36 +128,53 @@ DatabaseListener {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized ConnectionContext acceptConnection(TransportId t,
|
||||
byte[] encryptedIv) throws DbException {
|
||||
if(encryptedIv.length != IV_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
if(!initialised) initialise();
|
||||
Bytes b = new Bytes(encryptedIv);
|
||||
Context ctx = expected.get(b);
|
||||
// If the IV was not expected by this transport, reject the connection
|
||||
if(ctx == null || !ctx.transportId.equals(t)) return null;
|
||||
expected.remove(b);
|
||||
ContactId c = ctx.contactId;
|
||||
TransportIndex i = ctx.transportIndex;
|
||||
long connection = ctx.connection;
|
||||
ConnectionWindow w = ctx.window;
|
||||
// Get the secret and update the connection window
|
||||
byte[] secret = w.setSeen(connection);
|
||||
public void acceptConnection(final TransportId t, final byte[] encryptedIv,
|
||||
final Callback callback) {
|
||||
executor.execute(new Runnable() {
|
||||
public void run() {
|
||||
acceptConnectionSync(t, encryptedIv, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized void acceptConnectionSync(TransportId t,
|
||||
byte[] encryptedIv, Callback callback) {
|
||||
try {
|
||||
db.setConnectionWindow(c, i, w);
|
||||
} catch(NoSuchContactException e) {
|
||||
// The contact was removed - clean up when we get the event
|
||||
if(encryptedIv.length != IV_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
if(!initialised) initialise();
|
||||
Bytes b = new Bytes(encryptedIv);
|
||||
Context ctx = expected.get(b);
|
||||
if(ctx == null || !ctx.transportId.equals(t)) {
|
||||
callback.connectionRejected();
|
||||
return;
|
||||
}
|
||||
// The IV was expected
|
||||
expected.remove(b);
|
||||
ContactId c = ctx.contactId;
|
||||
TransportIndex i = ctx.transportIndex;
|
||||
long connection = ctx.connection;
|
||||
ConnectionWindow w = ctx.window;
|
||||
// Get the secret and update the connection window
|
||||
byte[] secret = w.setSeen(connection);
|
||||
try {
|
||||
db.setConnectionWindow(c, i, w);
|
||||
} catch(NoSuchContactException e) {
|
||||
// The contact was removed - clean up in eventOccurred()
|
||||
}
|
||||
// Update the set of expected IVs
|
||||
Iterator<Context> it = expected.values().iterator();
|
||||
while(it.hasNext()) {
|
||||
Context ctx1 = it.next();
|
||||
if(ctx1.contactId.equals(c) && ctx1.transportIndex.equals(i))
|
||||
it.remove();
|
||||
}
|
||||
calculateIvs(c, t, i, w);
|
||||
callback.connectionAccepted(new ConnectionContextImpl(c, i,
|
||||
connection, secret));
|
||||
} catch(DbException e) {
|
||||
callback.handleException(e);
|
||||
}
|
||||
// Update the set of expected IVs
|
||||
Iterator<Context> it = expected.values().iterator();
|
||||
while(it.hasNext()) {
|
||||
Context ctx1 = it.next();
|
||||
if(ctx1.contactId.equals(c) && ctx1.transportIndex.equals(i))
|
||||
it.remove();
|
||||
}
|
||||
calculateIvs(c, t, i, w);
|
||||
return new ConnectionContextImpl(c, i, connection, secret);
|
||||
}
|
||||
|
||||
public void eventOccurred(DatabaseEvent e) {
|
||||
|
||||
Reference in New Issue
Block a user