mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Check periodically for retransmittable packets. Bug #46.
This commit is contained in:
@@ -152,7 +152,7 @@ interface Database<T> {
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
boolean addTransport(T txn, TransportId t, long maxLatency)
|
||||
boolean addTransport(T txn, TransportId t, int maxLatency)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
@@ -460,7 +460,7 @@ interface Database<T> {
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
RetentionUpdate getRetentionUpdate(T txn, ContactId c, long maxLatency)
|
||||
RetentionUpdate getRetentionUpdate(T txn, ContactId c, int maxLatency)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
@@ -499,7 +499,7 @@ interface Database<T> {
|
||||
* Locking: write.
|
||||
*/
|
||||
SubscriptionUpdate getSubscriptionUpdate(T txn, ContactId c,
|
||||
long maxLatency) throws DbException;
|
||||
int maxLatency) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a collection of transport acks for the given contact, or null if
|
||||
@@ -511,11 +511,11 @@ interface Database<T> {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the maximum latencies of all local transports.
|
||||
* Returns the maximum latencies of all supported transports.
|
||||
* <p>
|
||||
* Locking: read.
|
||||
*/
|
||||
Map<TransportId, Long> getTransportLatencies(T txn) throws DbException;
|
||||
Map<TransportId, Integer> getTransportLatencies(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a collection of transport updates for the given contact and
|
||||
@@ -525,7 +525,7 @@ interface Database<T> {
|
||||
* Locking: write.
|
||||
*/
|
||||
Collection<TransportUpdate> getTransportUpdates(T txn, ContactId c,
|
||||
long maxLatency) throws DbException;
|
||||
int maxLatency) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the number of unread messages in each subscribed group.
|
||||
@@ -798,6 +798,6 @@ interface Database<T> {
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void updateExpiryTime(T txn, ContactId c, MessageId m, long maxLatency)
|
||||
void updateExpiryTime(T txn, ContactId c, MessageId m, int maxLatency)
|
||||
throws DbException;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addTransport(TransportId t, long maxLatency)
|
||||
public boolean addTransport(TransportId t, int maxLatency)
|
||||
throws DbException {
|
||||
boolean added;
|
||||
lock.writeLock().lock();
|
||||
@@ -357,7 +357,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
public Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
Collection<MessageId> ids;
|
||||
List<byte[]> messages = new ArrayList<byte[]>();
|
||||
lock.writeLock().lock();
|
||||
@@ -384,7 +384,7 @@ DatabaseCleaner.Callback {
|
||||
return Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
public Offer generateOffer(ContactId c, int maxMessages, long maxLatency)
|
||||
public Offer generateOffer(ContactId c, int maxMessages, int maxLatency)
|
||||
throws DbException {
|
||||
Collection<MessageId> ids;
|
||||
lock.writeLock().lock();
|
||||
@@ -432,7 +432,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
public Collection<byte[]> generateRequestedBatch(ContactId c, int maxLength,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
Collection<MessageId> ids;
|
||||
List<byte[]> messages = new ArrayList<byte[]>();
|
||||
lock.writeLock().lock();
|
||||
@@ -478,7 +478,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public RetentionUpdate generateRetentionUpdate(ContactId c, long maxLatency)
|
||||
public RetentionUpdate generateRetentionUpdate(ContactId c, int maxLatency)
|
||||
throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
@@ -519,7 +519,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
public SubscriptionUpdate generateSubscriptionUpdate(ContactId c,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
@@ -560,7 +560,7 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
public Collection<TransportUpdate> generateTransportUpdates(ContactId c,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
@@ -932,12 +932,13 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<TransportId, Long> getTransportLatencies() throws DbException {
|
||||
public Map<TransportId, Integer> getTransportLatencies()
|
||||
throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Map<TransportId, Long> latencies =
|
||||
Map<TransportId, Integer> latencies =
|
||||
db.getTransportLatencies(txn);
|
||||
db.commitTransaction(txn);
|
||||
return latencies;
|
||||
|
||||
@@ -11,13 +11,12 @@ class ExponentialBackoff {
|
||||
* transmissions increases exponentially. If the expiry time would
|
||||
* be greater than Long.MAX_VALUE, Long.MAX_VALUE is returned.
|
||||
*/
|
||||
static long calculateExpiry(long now, long maxLatency, int txCount) {
|
||||
static long calculateExpiry(long now, int maxLatency, int txCount) {
|
||||
if(now < 0) throw new IllegalArgumentException();
|
||||
if(maxLatency <= 0) throw new IllegalArgumentException();
|
||||
if(txCount < 0) throw new IllegalArgumentException();
|
||||
// The maximum round-trip time is twice the maximum latency
|
||||
long roundTrip = maxLatency * 2;
|
||||
if(roundTrip < 0) return Long.MAX_VALUE;
|
||||
long roundTrip = maxLatency * 2L;
|
||||
// The interval between transmissions is roundTrip * 2 ^ txCount
|
||||
for(int i = 0; i < txCount; i++) {
|
||||
roundTrip <<= 1;
|
||||
|
||||
@@ -62,8 +62,8 @@ import org.briarproject.api.transport.TemporarySecret;
|
||||
*/
|
||||
abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
private static final int SCHEMA_VERSION = 6;
|
||||
private static final int MIN_SCHEMA_VERSION = 5;
|
||||
private static final int SCHEMA_VERSION = 7;
|
||||
private static final int MIN_SCHEMA_VERSION = 7;
|
||||
|
||||
private static final String CREATE_SETTINGS =
|
||||
"CREATE TABLE settings"
|
||||
@@ -213,7 +213,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private static final String CREATE_TRANSPORTS =
|
||||
"CREATE TABLE transports"
|
||||
+ " (transportId VARCHAR NOT NULL,"
|
||||
+ " maxLatency BIGINT NOT NULL,"
|
||||
+ " maxLatency INT NOT NULL,"
|
||||
+ " PRIMARY KEY (transportId))";
|
||||
|
||||
private static final String CREATE_TRANSPORT_CONFIGS =
|
||||
@@ -866,7 +866,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addTransport(Connection txn, TransportId t, long maxLatency)
|
||||
public boolean addTransport(Connection txn, TransportId t, int maxLatency)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -2024,7 +2024,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
public RetentionUpdate getRetentionUpdate(Connection txn, ContactId c,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
long now = clock.currentTimeMillis();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -2202,7 +2202,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
public SubscriptionUpdate getSubscriptionUpdate(Connection txn, ContactId c,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
long now = clock.currentTimeMillis();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -2296,7 +2296,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<TransportId, Long> getTransportLatencies(Connection txn)
|
||||
public Map<TransportId, Integer> getTransportLatencies(Connection txn)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -2304,10 +2304,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
String sql = "SELECT transportId, maxLatency FROM transports";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
Map<TransportId, Long> latencies = new HashMap<TransportId, Long>();
|
||||
Map<TransportId, Integer> latencies =
|
||||
new HashMap<TransportId, Integer>();
|
||||
while(rs.next()){
|
||||
TransportId id = new TransportId(rs.getString(1));
|
||||
latencies.put(id, rs.getLong(2));
|
||||
latencies.put(id, rs.getInt(2));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -2320,7 +2321,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
public Collection<TransportUpdate> getTransportUpdates(Connection txn,
|
||||
ContactId c, long maxLatency) throws DbException {
|
||||
ContactId c, int maxLatency) throws DbException {
|
||||
long now = clock.currentTimeMillis();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -3301,7 +3302,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
public void updateExpiryTime(Connection txn, ContactId c, MessageId m,
|
||||
long maxLatency) throws DbException {
|
||||
int maxLatency) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
|
||||
@@ -285,7 +285,7 @@ abstract class Connector extends Thread {
|
||||
db.setRemoteProperties(contactId, remoteProps);
|
||||
// Create an endpoint for each transport shared with the contact
|
||||
List<TransportId> ids = new ArrayList<TransportId>();
|
||||
Map<TransportId, Long> latencies = db.getTransportLatencies();
|
||||
Map<TransportId, Integer> latencies = db.getTransportLatencies();
|
||||
for(TransportId id : localProps.keySet()) {
|
||||
if(latencies.containsKey(id) && remoteProps.containsKey(id))
|
||||
ids.add(id);
|
||||
@@ -296,7 +296,7 @@ abstract class Connector extends Thread {
|
||||
for(int i = 0; i < size; i++) {
|
||||
TransportId id = ids.get(i);
|
||||
Endpoint ep = new Endpoint(contactId, id, epoch, alice);
|
||||
long maxLatency = latencies.get(id);
|
||||
int maxLatency = latencies.get(id);
|
||||
try {
|
||||
db.addEndpoint(ep);
|
||||
} catch(NoSuchTransportException e) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -37,7 +36,6 @@ import org.briarproject.api.messaging.Ack;
|
||||
import org.briarproject.api.messaging.MessagingSession;
|
||||
import org.briarproject.api.messaging.Offer;
|
||||
import org.briarproject.api.messaging.PacketWriter;
|
||||
import org.briarproject.api.messaging.PacketWriterFactory;
|
||||
import org.briarproject.api.messaging.Request;
|
||||
import org.briarproject.api.messaging.RetentionAck;
|
||||
import org.briarproject.api.messaging.RetentionUpdate;
|
||||
@@ -45,16 +43,18 @@ import org.briarproject.api.messaging.SubscriptionAck;
|
||||
import org.briarproject.api.messaging.SubscriptionUpdate;
|
||||
import org.briarproject.api.messaging.TransportAck;
|
||||
import org.briarproject.api.messaging.TransportUpdate;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
/**
|
||||
* An outgoing {@link org.briarproject.api.messaging.MessagingSession
|
||||
* MessagingSession} suitable for duplex transports. The session offers
|
||||
* messages before sending them, keeps its output stream open when there are no
|
||||
* more packets to send, and reacts to events that make packets available to
|
||||
* send.
|
||||
* packets to send, and reacts to events that make packets available to send.
|
||||
*/
|
||||
class DuplexOutgoingSession implements MessagingSession, EventListener {
|
||||
|
||||
// Check for retransmittable packets once every 60 seconds
|
||||
private static final int RETX_QUERY_INTERVAL = 60 * 1000;
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(DuplexOutgoingSession.class.getName());
|
||||
|
||||
@@ -66,28 +66,32 @@ class DuplexOutgoingSession implements MessagingSession, EventListener {
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
private final EventBus eventBus;
|
||||
private final Clock clock;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final long maxLatency, maxIdleTime;
|
||||
private final OutputStream out;
|
||||
private final int maxLatency, maxIdleTime;
|
||||
private final PacketWriter packetWriter;
|
||||
private final BlockingQueue<ThrowingRunnable<IOException>> writerTasks;
|
||||
|
||||
// The following must only be accessed on the writer thread
|
||||
private long nextKeepalive = 0, nextRetxQuery = 0;
|
||||
private boolean dataToFlush = true;
|
||||
|
||||
private volatile boolean interrupted = false;
|
||||
|
||||
DuplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
|
||||
EventBus eventBus, PacketWriterFactory packetWriterFactory,
|
||||
ContactId contactId, TransportId transportId, long maxLatency,
|
||||
long maxIdleTime, OutputStream out) {
|
||||
EventBus eventBus, Clock clock, ContactId contactId,
|
||||
TransportId transportId, int maxLatency, int maxIdleTime,
|
||||
PacketWriter packetWriter) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.eventBus = eventBus;
|
||||
this.clock = clock;
|
||||
this.contactId = contactId;
|
||||
this.transportId = transportId;
|
||||
this.maxLatency = maxLatency;
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
this.out = out;
|
||||
packetWriter = packetWriterFactory.createPacketWriter(out);
|
||||
this.packetWriter = packetWriter;
|
||||
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
|
||||
}
|
||||
|
||||
@@ -105,21 +109,50 @@ class DuplexOutgoingSession implements MessagingSession, EventListener {
|
||||
dbExecutor.execute(new GenerateBatch());
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
dbExecutor.execute(new GenerateRequest());
|
||||
long now = clock.currentTimeMillis();
|
||||
nextKeepalive = now + maxIdleTime;
|
||||
nextRetxQuery = now + RETX_QUERY_INTERVAL;
|
||||
// Write packets until interrupted
|
||||
try {
|
||||
while(!interrupted) {
|
||||
// Flush the stream if it's going to be idle
|
||||
if(writerTasks.isEmpty()) out.flush();
|
||||
ThrowingRunnable<IOException> task =
|
||||
writerTasks.poll(maxIdleTime, MILLISECONDS);
|
||||
if(task == null) {
|
||||
LOG.info("Idle timeout");
|
||||
continue; // Flush and wait again
|
||||
// Work out how long we should wait for a packet
|
||||
now = clock.currentTimeMillis();
|
||||
long wait = Math.min(nextKeepalive, nextRetxQuery) - now;
|
||||
if(wait < 0) wait = 0;
|
||||
// Flush any unflushed data if we're going to wait
|
||||
if(wait > 0 && dataToFlush && writerTasks.isEmpty()) {
|
||||
packetWriter.flush();
|
||||
dataToFlush = false;
|
||||
nextKeepalive = now + maxIdleTime;
|
||||
}
|
||||
// Wait for a packet
|
||||
ThrowingRunnable<IOException> task = writerTasks.poll(wait,
|
||||
MILLISECONDS);
|
||||
if(task == null) {
|
||||
now = clock.currentTimeMillis();
|
||||
if(now >= nextRetxQuery) {
|
||||
// Check for retransmittable packets
|
||||
dbExecutor.execute(new GenerateTransportUpdates());
|
||||
dbExecutor.execute(new GenerateSubscriptionUpdate());
|
||||
dbExecutor.execute(new GenerateRetentionUpdate());
|
||||
dbExecutor.execute(new GenerateBatch());
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
nextRetxQuery = now + RETX_QUERY_INTERVAL;
|
||||
}
|
||||
if(now >= nextKeepalive) {
|
||||
// Flush the stream to keep it alive
|
||||
packetWriter.flush();
|
||||
dataToFlush = false;
|
||||
nextKeepalive = now + maxIdleTime;
|
||||
}
|
||||
} else if(task == CLOSE) {
|
||||
break;
|
||||
} else {
|
||||
task.run();
|
||||
dataToFlush = true;
|
||||
}
|
||||
if(task == CLOSE) break;
|
||||
task.run();
|
||||
}
|
||||
out.flush();
|
||||
if(dataToFlush) packetWriter.flush();
|
||||
} catch(InterruptedException e) {
|
||||
LOG.info("Interrupted while waiting for a packet to write");
|
||||
Thread.currentThread().interrupt();
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.messaging;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
@@ -25,7 +24,6 @@ import org.briarproject.api.messaging.MessageVerifier;
|
||||
import org.briarproject.api.messaging.MessagingSession;
|
||||
import org.briarproject.api.messaging.Offer;
|
||||
import org.briarproject.api.messaging.PacketReader;
|
||||
import org.briarproject.api.messaging.PacketReaderFactory;
|
||||
import org.briarproject.api.messaging.Request;
|
||||
import org.briarproject.api.messaging.RetentionAck;
|
||||
import org.briarproject.api.messaging.RetentionUpdate;
|
||||
@@ -56,9 +54,8 @@ class IncomingSession implements MessagingSession, EventListener {
|
||||
|
||||
IncomingSession(DatabaseComponent db, Executor dbExecutor,
|
||||
Executor cryptoExecutor, EventBus eventBus,
|
||||
MessageVerifier messageVerifier,
|
||||
PacketReaderFactory packetReaderFactory, ContactId contactId,
|
||||
TransportId transportId, InputStream in) {
|
||||
MessageVerifier messageVerifier, ContactId contactId,
|
||||
TransportId transportId, PacketReader packetReader) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
@@ -66,7 +63,7 @@ class IncomingSession implements MessagingSession, EventListener {
|
||||
this.messageVerifier = messageVerifier;
|
||||
this.contactId = contactId;
|
||||
this.transportId = transportId;
|
||||
packetReader = packetReaderFactory.createPacketReader(in);
|
||||
this.packetReader = packetReader;
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
|
||||
@@ -15,8 +15,11 @@ import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.messaging.MessageVerifier;
|
||||
import org.briarproject.api.messaging.MessagingSession;
|
||||
import org.briarproject.api.messaging.MessagingSessionFactory;
|
||||
import org.briarproject.api.messaging.PacketReader;
|
||||
import org.briarproject.api.messaging.PacketReaderFactory;
|
||||
import org.briarproject.api.messaging.PacketWriter;
|
||||
import org.briarproject.api.messaging.PacketWriterFactory;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
class MessagingSessionFactoryImpl implements MessagingSessionFactory {
|
||||
|
||||
@@ -24,6 +27,7 @@ class MessagingSessionFactoryImpl implements MessagingSessionFactory {
|
||||
private final Executor dbExecutor, cryptoExecutor;
|
||||
private final MessageVerifier messageVerifier;
|
||||
private final EventBus eventBus;
|
||||
private final Clock clock;
|
||||
private final PacketReaderFactory packetReaderFactory;
|
||||
private final PacketWriterFactory packetWriterFactory;
|
||||
|
||||
@@ -31,7 +35,7 @@ class MessagingSessionFactoryImpl implements MessagingSessionFactory {
|
||||
MessagingSessionFactoryImpl(DatabaseComponent db,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
@CryptoExecutor Executor cryptoExecutor,
|
||||
MessageVerifier messageVerifier, EventBus eventBus,
|
||||
MessageVerifier messageVerifier, EventBus eventBus, Clock clock,
|
||||
PacketReaderFactory packetReaderFactory,
|
||||
PacketWriterFactory packetWriterFactory) {
|
||||
this.db = db;
|
||||
@@ -39,26 +43,29 @@ class MessagingSessionFactoryImpl implements MessagingSessionFactory {
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.messageVerifier = messageVerifier;
|
||||
this.eventBus = eventBus;
|
||||
this.clock = clock;
|
||||
this.packetReaderFactory = packetReaderFactory;
|
||||
this.packetWriterFactory = packetWriterFactory;
|
||||
}
|
||||
|
||||
public MessagingSession createIncomingSession(ContactId c, TransportId t,
|
||||
InputStream in) {
|
||||
PacketReader packetReader = packetReaderFactory.createPacketReader(in);
|
||||
return new IncomingSession(db, dbExecutor, cryptoExecutor, eventBus,
|
||||
messageVerifier, packetReaderFactory, c, t, in);
|
||||
messageVerifier, c, t, packetReader);
|
||||
}
|
||||
|
||||
public MessagingSession createSimplexOutgoingSession(ContactId c,
|
||||
TransportId t, long maxLatency, OutputStream out) {
|
||||
return new SimplexOutgoingSession(db, dbExecutor, eventBus,
|
||||
packetWriterFactory, c, t, maxLatency, out);
|
||||
TransportId t, int maxLatency, OutputStream out) {
|
||||
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
|
||||
return new SimplexOutgoingSession(db, dbExecutor, eventBus, c, t,
|
||||
maxLatency, packetWriter);
|
||||
}
|
||||
|
||||
public MessagingSession createDuplexOutgoingSession(ContactId c,
|
||||
TransportId t, long maxLatency, long maxIdleTime,
|
||||
OutputStream out) {
|
||||
return new DuplexOutgoingSession(db, dbExecutor, eventBus,
|
||||
packetWriterFactory, c, t, maxLatency, maxIdleTime, out);
|
||||
TransportId t, int maxLatency, int maxIdleTime, OutputStream out) {
|
||||
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
|
||||
return new DuplexOutgoingSession(db, dbExecutor, eventBus, clock, c, t,
|
||||
maxLatency, maxIdleTime, packetWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,4 +143,8 @@ class PacketWriterImpl implements PacketWriter {
|
||||
w.writeInteger(u.getVersion());
|
||||
w.writeStructEnd();
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -26,7 +25,6 @@ import org.briarproject.api.event.TransportRemovedEvent;
|
||||
import org.briarproject.api.messaging.Ack;
|
||||
import org.briarproject.api.messaging.MessagingSession;
|
||||
import org.briarproject.api.messaging.PacketWriter;
|
||||
import org.briarproject.api.messaging.PacketWriterFactory;
|
||||
import org.briarproject.api.messaging.RetentionAck;
|
||||
import org.briarproject.api.messaging.RetentionUpdate;
|
||||
import org.briarproject.api.messaging.SubscriptionAck;
|
||||
@@ -55,8 +53,7 @@ class SimplexOutgoingSession implements MessagingSession, EventListener {
|
||||
private final EventBus eventBus;
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
private final long maxLatency;
|
||||
private final OutputStream out;
|
||||
private final int maxLatency;
|
||||
private final PacketWriter packetWriter;
|
||||
private final AtomicInteger outstandingQueries;
|
||||
private final BlockingQueue<ThrowingRunnable<IOException>> writerTasks;
|
||||
@@ -64,17 +61,15 @@ class SimplexOutgoingSession implements MessagingSession, EventListener {
|
||||
private volatile boolean interrupted = false;
|
||||
|
||||
SimplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
|
||||
EventBus eventBus, PacketWriterFactory packetWriterFactory,
|
||||
ContactId contactId, TransportId transportId, long maxLatency,
|
||||
OutputStream out) {
|
||||
EventBus eventBus, ContactId contactId, TransportId transportId,
|
||||
int maxLatency, PacketWriter packetWriter) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.eventBus = eventBus;
|
||||
this.contactId = contactId;
|
||||
this.transportId = transportId;
|
||||
this.maxLatency = maxLatency;
|
||||
this.out = out;
|
||||
packetWriter = packetWriterFactory.createPacketWriter(out);
|
||||
this.packetWriter = packetWriter;
|
||||
outstandingQueries = new AtomicInteger(8); // One per type of packet
|
||||
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
|
||||
}
|
||||
@@ -98,7 +93,7 @@ class SimplexOutgoingSession implements MessagingSession, EventListener {
|
||||
if(task == CLOSE) break;
|
||||
task.run();
|
||||
}
|
||||
out.flush();
|
||||
packetWriter.flush();
|
||||
} catch(InterruptedException e) {
|
||||
LOG.info("Interrupted while waiting for a packet to write");
|
||||
Thread.currentThread().interrupt();
|
||||
|
||||
@@ -28,8 +28,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
protected final Executor ioExecutor;
|
||||
protected final FileUtils fileUtils;
|
||||
protected final SimplexPluginCallback callback;
|
||||
protected final int maxFrameLength;
|
||||
protected final long maxLatency;
|
||||
protected final int maxFrameLength, maxLatency;
|
||||
|
||||
protected volatile boolean running = false;
|
||||
|
||||
@@ -40,7 +39,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
|
||||
protected FilePlugin(Executor ioExecutor, FileUtils fileUtils,
|
||||
SimplexPluginCallback callback, int maxFrameLength,
|
||||
long maxLatency) {
|
||||
int maxLatency) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.fileUtils = fileUtils;
|
||||
this.callback = callback;
|
||||
@@ -52,12 +51,12 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
return maxFrameLength;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
public int getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
return Long.MAX_VALUE; // We don't need keepalives
|
||||
public int getMaxIdleTime() {
|
||||
return Integer.MAX_VALUE; // We don't need keepalives
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
|
||||
@@ -31,11 +31,11 @@ class FileTransportWriter implements TransportConnectionWriter {
|
||||
return plugin.getMaxFrameLength();
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
public int getMaxLatency() {
|
||||
return plugin.getMaxLatency();
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
public int getMaxIdleTime() {
|
||||
return plugin.getMaxIdleTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
static final TransportId ID = new TransportId("lan");
|
||||
|
||||
LanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval) {
|
||||
int maxFrameLength, int maxLatency, int maxIdleTime,
|
||||
int pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency, maxIdleTime,
|
||||
pollingInterval);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
|
||||
public class LanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final int MAX_FRAME_LENGTH = 1024;
|
||||
private static final long MAX_LATENCY = 60 * 1000; // 1 minute
|
||||
private static final long MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
|
||||
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
||||
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final int POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
|
||||
|
||||
private final Executor ioExecutor;
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
|
||||
protected final Executor ioExecutor;
|
||||
protected final DuplexPluginCallback callback;
|
||||
protected final int maxFrameLength, socketTimeout;
|
||||
protected final long maxLatency, maxIdleTime, pollingInterval;
|
||||
protected final int maxFrameLength, maxLatency, maxIdleTime;
|
||||
protected final int pollingInterval, socketTimeout;
|
||||
|
||||
protected volatile boolean running = false;
|
||||
protected volatile ServerSocket socket = null;
|
||||
@@ -53,28 +53,28 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
protected abstract boolean isConnectable(InetSocketAddress remote);
|
||||
|
||||
protected TcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval) {
|
||||
int maxFrameLength, int maxLatency, int maxIdleTime,
|
||||
int pollingInterval) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.callback = callback;
|
||||
this.maxFrameLength = maxFrameLength;
|
||||
this.maxLatency = maxLatency;
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
this.pollingInterval = pollingInterval;
|
||||
if(2 * maxIdleTime > Integer.MAX_VALUE)
|
||||
if(maxIdleTime > Integer.MAX_VALUE / 2)
|
||||
socketTimeout = Integer.MAX_VALUE;
|
||||
else socketTimeout = (int) (2 * maxIdleTime);
|
||||
else socketTimeout = maxIdleTime * 2;
|
||||
}
|
||||
|
||||
public int getMaxFrameLength() {
|
||||
return maxFrameLength;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
public int getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
public int getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
public long getPollingInterval() {
|
||||
public int getPollingInterval() {
|
||||
return pollingInterval;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,11 +63,11 @@ class TcpTransportConnection implements DuplexTransportConnection {
|
||||
return plugin.getMaxFrameLength();
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
public int getMaxLatency() {
|
||||
return plugin.getMaxLatency();
|
||||
}
|
||||
|
||||
public long getMaxIdleTime() {
|
||||
public int getMaxIdleTime() {
|
||||
return plugin.getMaxIdleTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ class WanTcpPlugin extends TcpPlugin {
|
||||
|
||||
private volatile MappingResult mappingResult;
|
||||
|
||||
WanTcpPlugin(Executor ioExecutor, DuplexPluginCallback callback,
|
||||
int maxFrameLength, long maxLatency, long maxIdleTime,
|
||||
long pollingInterval, PortMapper portMapper) {
|
||||
WanTcpPlugin(Executor ioExecutor, PortMapper portMapper,
|
||||
DuplexPluginCallback callback, int maxFrameLength, int maxLatency,
|
||||
int maxIdleTime, int pollingInterval) {
|
||||
super(ioExecutor, callback, maxFrameLength, maxLatency, maxIdleTime,
|
||||
pollingInterval);
|
||||
this.portMapper = portMapper;
|
||||
|
||||
@@ -11,9 +11,9 @@ import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
|
||||
public class WanTcpPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final int MAX_FRAME_LENGTH = 1024;
|
||||
private static final long MAX_LATENCY = 60 * 1000; // 1 minute
|
||||
private static final long MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final long POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
||||
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final int POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
private final Executor ioExecutor;
|
||||
private final ShutdownManager shutdownManager;
|
||||
@@ -29,8 +29,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
|
||||
}
|
||||
|
||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||
return new WanTcpPlugin(ioExecutor, callback, MAX_FRAME_LENGTH,
|
||||
MAX_LATENCY, MAX_IDLE_TIME, POLLING_INTERVAL,
|
||||
new PortMapperImpl(shutdownManager));
|
||||
return new WanTcpPlugin(ioExecutor, new PortMapperImpl(shutdownManager),
|
||||
callback, MAX_FRAME_LENGTH, MAX_LATENCY, MAX_IDLE_TIME,
|
||||
POLLING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
|
||||
private final Timer timer;
|
||||
|
||||
// All of the following are locking: this
|
||||
private final Map<TransportId, Long> maxLatencies;
|
||||
private final Map<TransportId, Integer> maxLatencies;
|
||||
private final Map<EndpointKey, TemporarySecret> oldSecrets;
|
||||
private final Map<EndpointKey, TemporarySecret> currentSecrets;
|
||||
private final Map<EndpointKey, TemporarySecret> newSecrets;
|
||||
@@ -66,7 +66,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
|
||||
this.tagRecogniser = tagRecogniser;
|
||||
this.clock = clock;
|
||||
this.timer = timer;
|
||||
maxLatencies = new HashMap<TransportId, Long>();
|
||||
maxLatencies = new HashMap<TransportId, Integer>();
|
||||
oldSecrets = new HashMap<EndpointKey, TemporarySecret>();
|
||||
currentSecrets = new HashMap<EndpointKey, TemporarySecret>();
|
||||
newSecrets = new HashMap<EndpointKey, TemporarySecret>();
|
||||
@@ -116,7 +116,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
|
||||
Collection<TemporarySecret> dead = new ArrayList<TemporarySecret>();
|
||||
for(TemporarySecret s : secrets) {
|
||||
// Discard the secret if the transport has been removed
|
||||
Long maxLatency = maxLatencies.get(s.getTransportId());
|
||||
Integer maxLatency = maxLatencies.get(s.getTransportId());
|
||||
if(maxLatency == null) {
|
||||
LOG.info("Discarding obsolete secret");
|
||||
ByteUtils.erase(s.getSecret());
|
||||
@@ -168,7 +168,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
|
||||
Collection<TemporarySecret> created = new ArrayList<TemporarySecret>();
|
||||
for(Entry<EndpointKey, TemporarySecret> e : newest.entrySet()) {
|
||||
TemporarySecret s = e.getValue();
|
||||
Long maxLatency = maxLatencies.get(s.getTransportId());
|
||||
Integer maxLatency = maxLatencies.get(s.getTransportId());
|
||||
if(maxLatency == null) throw new IllegalStateException();
|
||||
// Work out which rotation period we're in
|
||||
long elapsed = now - s.getEpoch();
|
||||
@@ -255,7 +255,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, EventListener {
|
||||
return new StreamContext(c, t, secret, streamNumber, s.getAlice());
|
||||
}
|
||||
|
||||
public synchronized void endpointAdded(Endpoint ep, long maxLatency,
|
||||
public synchronized void endpointAdded(Endpoint ep, int maxLatency,
|
||||
byte[] initialSecret) {
|
||||
maxLatencies.put(ep.getTransportId(), maxLatency);
|
||||
// Work out which rotation period we're in
|
||||
|
||||
Reference in New Issue
Block a user