mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Retransmit messages based on maximum latency of transport.
This commit is contained in:
@@ -80,23 +80,25 @@ public interface DatabaseComponent {
|
||||
|
||||
/**
|
||||
* Generates a batch of raw messages for the given contact, with a total
|
||||
* length less than or equal to the given length. Returns null if
|
||||
* there are no sendable messages that fit in the given length.
|
||||
* length less than or equal to the given length, for transmission over a
|
||||
* transport with the given maximum latency. Returns null if there are no
|
||||
* sendable messages that fit in the given length.
|
||||
*/
|
||||
Collection<byte[]> generateBatch(ContactId c, int maxLength)
|
||||
throws DbException;
|
||||
Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
long maxLatency) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a batch of raw messages for the given contact from the given
|
||||
* collection of requested messages, with a total length less than or equal
|
||||
* to the given length. Any messages that were either added to the batch,
|
||||
* or were considered but are no longer sendable to the contact, are
|
||||
* removed from the collection of requested messages before returning.
|
||||
* Returns null if there are no sendable messages that fit in the given
|
||||
* length.
|
||||
* to the given length, for transmission over a transport with the given
|
||||
* maximum latency. Any messages that were either added to the batch, or
|
||||
* were considered but are no longer sendable to the contact, are removed
|
||||
* from the collection of requested messages before returning. Returns null
|
||||
* if there are no sendable messages that fit in the given length.
|
||||
*/
|
||||
Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
Collection<MessageId> requested) throws DbException;
|
||||
long maxLatency, Collection<MessageId> requested)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an offer for the given contact. Returns null if there are no
|
||||
|
||||
@@ -11,6 +11,9 @@ import java.io.OutputStream;
|
||||
*/
|
||||
public interface DuplexTransportConnection {
|
||||
|
||||
/** Returns the maximum latency of the transport in milliseconds. */
|
||||
long getMaxLatency();
|
||||
|
||||
/** Returns an input stream for reading from the connection. */
|
||||
InputStream getInputStream() throws IOException;
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ public interface SimplexTransportWriter {
|
||||
/** Returns the capacity of the transport in bytes. */
|
||||
long getCapacity();
|
||||
|
||||
/** Returns the maximum latency of the transport in milliseconds. */
|
||||
long getMaxLatency();
|
||||
|
||||
/** Returns an output stream for writing to the transport. */
|
||||
OutputStream getOutputStream() throws IOException;
|
||||
|
||||
|
||||
@@ -488,8 +488,8 @@ DatabaseCleaner.Callback {
|
||||
return new Ack(acked);
|
||||
}
|
||||
|
||||
public Collection<byte[]> generateBatch(ContactId c, int maxLength)
|
||||
throws DbException {
|
||||
public Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
long maxLatency) throws DbException {
|
||||
Collection<MessageId> ids;
|
||||
List<byte[]> messages = new ArrayList<byte[]>();
|
||||
// Get some sendable messages from the database
|
||||
@@ -504,9 +504,8 @@ DatabaseCleaner.Callback {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
ids = db.getSendableMessages(txn, c, maxLength);
|
||||
for(MessageId m : ids) {
|
||||
for(MessageId m : ids)
|
||||
messages.add(db.getRawMessage(txn, m));
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
@@ -519,13 +518,14 @@ DatabaseCleaner.Callback {
|
||||
messageLock.readLock().unlock();
|
||||
}
|
||||
if(messages.isEmpty()) return null;
|
||||
// Calculate the expiry time of the messages
|
||||
long expiry = calculateExpiryTime(maxLatency);
|
||||
// Record the messages as sent
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
// FIXME: Calculate the expiry time
|
||||
db.addOutstandingMessages(txn, c, ids, Long.MAX_VALUE);
|
||||
db.addOutstandingMessages(txn, c, ids, expiry);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
@@ -541,7 +541,8 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
|
||||
public Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
Collection<MessageId> requested) throws DbException {
|
||||
long maxLatency, Collection<MessageId> requested)
|
||||
throws DbException {
|
||||
Collection<MessageId> ids = new ArrayList<MessageId>();
|
||||
List<byte[]> messages = new ArrayList<byte[]>();
|
||||
// Get some sendable messages from the database
|
||||
@@ -579,13 +580,14 @@ DatabaseCleaner.Callback {
|
||||
messageLock.readLock().unlock();
|
||||
}
|
||||
if(messages.isEmpty()) return null;
|
||||
// Calculate the expiry times of the messages
|
||||
long expiry = calculateExpiryTime(maxLatency);
|
||||
// Record the messages as sent
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
// FIXME: Calculate the expiry time
|
||||
db.addOutstandingMessages(txn, c, ids, Long.MAX_VALUE);
|
||||
db.addOutstandingMessages(txn, c, ids, expiry);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
@@ -600,6 +602,14 @@ DatabaseCleaner.Callback {
|
||||
return Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
private long calculateExpiryTime(long maxLatency) {
|
||||
long roundTrip = maxLatency * 2;
|
||||
if(roundTrip < 0) roundTrip = Long.MAX_VALUE; // Overflow
|
||||
long expiry = clock.currentTimeMillis() + roundTrip;
|
||||
if(expiry < 0) expiry = Long.MAX_VALUE; // Overflow
|
||||
return expiry;
|
||||
}
|
||||
|
||||
public Offer generateOffer(ContactId c, int maxMessages)
|
||||
throws DbException {
|
||||
Collection<MessageId> offered;
|
||||
|
||||
@@ -156,7 +156,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " (messageId HASH NOT NULL,"
|
||||
+ " contactId INT NOT NULL,"
|
||||
+ " seen BOOLEAN NOT NULL,"
|
||||
+ " transmissionCount INT NOT NULL,"
|
||||
+ " expiry BIGINT NOT NULL,"
|
||||
+ " PRIMARY KEY (messageId, contactId),"
|
||||
+ " FOREIGN KEY (messageId)"
|
||||
@@ -651,16 +650,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
Collection<MessageId> sent, long expiry) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
// Update the transmission count and expiry time of each message
|
||||
String sql = "UPDATE statuses SET expiry = ?,"
|
||||
+ " transmissionCount = transmissionCount + ?"
|
||||
// Update the expiry time of each message
|
||||
String sql = "UPDATE statuses SET expiry = ?"
|
||||
+ " WHERE messageId = ? AND contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setLong(1, expiry);
|
||||
ps.setInt(2, 1);
|
||||
ps.setInt(4, c.getInt());
|
||||
ps.setInt(3, c.getInt());
|
||||
for(MessageId m : sent) {
|
||||
ps.setBytes(3, m.getBytes());
|
||||
ps.setBytes(2, m.getBytes());
|
||||
ps.addBatch();
|
||||
}
|
||||
int[] batchAffected = ps.executeBatch();
|
||||
@@ -713,8 +710,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "INSERT INTO statuses"
|
||||
+ " (messageId, contactId, seen, transmissionCount, expiry)"
|
||||
+ " VALUES (?, ?, ?, ZERO(), ZERO())";
|
||||
+ " (messageId, contactId, seen, expiry)"
|
||||
+ " VALUES (?, ?, ?, ZERO())";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
ps.setInt(2, c.getInt());
|
||||
|
||||
@@ -467,7 +467,8 @@ abstract class DuplexConnection implements DatabaseListener {
|
||||
assert writer != null;
|
||||
try {
|
||||
Collection<byte[]> batch = db.generateBatch(contactId,
|
||||
Integer.MAX_VALUE, requested);
|
||||
Integer.MAX_VALUE, transport.getMaxLatency(),
|
||||
requested);
|
||||
if(batch == null) new GenerateOffer().run();
|
||||
else writerTasks.add(new WriteBatch(batch, requested));
|
||||
} catch(DbException e) {
|
||||
|
||||
@@ -69,6 +69,7 @@ class OutgoingSimplexConnection {
|
||||
throw new EOFException();
|
||||
PacketWriter writer = packetWriterFactory.createPacketWriter(out,
|
||||
transport.shouldFlush());
|
||||
long maxLatency = transport.getMaxLatency();
|
||||
// Send the initial packets: updates and acks
|
||||
boolean hasSpace = writeTransportAcks(conn, writer);
|
||||
if(hasSpace) hasSpace = writeTransportUpdates(conn, writer);
|
||||
@@ -89,12 +90,13 @@ class OutgoingSimplexConnection {
|
||||
// Write messages until you can't write messages no more
|
||||
capacity = conn.getRemainingCapacity();
|
||||
int maxLength = (int) Math.min(capacity, MAX_PACKET_LENGTH);
|
||||
Collection<byte[]> batch = db.generateBatch(contactId, maxLength);
|
||||
Collection<byte[]> batch = db.generateBatch(contactId, maxLength,
|
||||
maxLatency);
|
||||
while(batch != null) {
|
||||
for(byte[] raw : batch) writer.writeMessage(raw);
|
||||
capacity = conn.getRemainingCapacity();
|
||||
maxLength = (int) Math.min(capacity, MAX_PACKET_LENGTH);
|
||||
batch = db.generateBatch(contactId, maxLength);
|
||||
batch = db.generateBatch(contactId, maxLength, maxLatency);
|
||||
}
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
@@ -155,7 +155,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
return;
|
||||
}
|
||||
BluetoothTransportConnection conn =
|
||||
new BluetoothTransportConnection(s);
|
||||
new BluetoothTransportConnection(s, maxLatency);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
if(!running) return;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
private DuplexTransportConnection connect(String url) {
|
||||
try {
|
||||
StreamConnection s = (StreamConnection) Connector.open(url);
|
||||
return new BluetoothTransportConnection(s);
|
||||
return new BluetoothTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return null;
|
||||
@@ -294,7 +294,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
// Try to accept a connection and close the socket
|
||||
try {
|
||||
StreamConnection s = scn.acceptAndOpen();
|
||||
return new BluetoothTransportConnection(s);
|
||||
return new BluetoothTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
// This is expected when the socket is closed
|
||||
if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
|
||||
|
||||
@@ -11,9 +11,15 @@ import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
|
||||
class BluetoothTransportConnection implements DuplexTransportConnection {
|
||||
|
||||
private final StreamConnection stream;
|
||||
private final long maxLatency;
|
||||
|
||||
BluetoothTransportConnection(StreamConnection stream) {
|
||||
BluetoothTransportConnection(StreamConnection stream, long maxLatency) {
|
||||
this.stream = stream;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
|
||||
@@ -188,7 +188,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return;
|
||||
}
|
||||
DroidtoothTransportConnection conn =
|
||||
new DroidtoothTransportConnection(s);
|
||||
new DroidtoothTransportConnection(s, maxLatency);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
if(!running) return;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
try {
|
||||
BluetoothSocket s = InsecureBluetooth.createSocket(d, u);
|
||||
s.connect();
|
||||
return new DroidtoothTransportConnection(s);
|
||||
return new DroidtoothTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return null;
|
||||
@@ -310,7 +310,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
// Return the first connection received by the socket, if any
|
||||
try {
|
||||
return new DroidtoothTransportConnection(ss.accept((int) timeout));
|
||||
BluetoothSocket s = ss.accept((int) timeout);
|
||||
return new DroidtoothTransportConnection(s, maxLatency);
|
||||
} catch(SocketTimeoutException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Invitation timed out");
|
||||
return null;
|
||||
|
||||
@@ -10,9 +10,15 @@ import android.bluetooth.BluetoothSocket;
|
||||
class DroidtoothTransportConnection implements DuplexTransportConnection {
|
||||
|
||||
private final BluetoothSocket socket;
|
||||
private final long maxLatency;
|
||||
|
||||
DroidtoothTransportConnection(BluetoothSocket socket) {
|
||||
DroidtoothTransportConnection(BluetoothSocket socket, long maxLatency) {
|
||||
this.socket = socket;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
|
||||
@@ -28,6 +28,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
|
||||
protected final Executor pluginExecutor;
|
||||
protected final SimplexPluginCallback callback;
|
||||
protected final long maxLatency;
|
||||
|
||||
protected volatile boolean running = false;
|
||||
|
||||
@@ -37,9 +38,10 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
protected abstract void readerFinished(File f);
|
||||
|
||||
protected FilePlugin(@PluginExecutor Executor pluginExecutor,
|
||||
SimplexPluginCallback callback) {
|
||||
SimplexPluginCallback callback, long maxLatency) {
|
||||
this.pluginExecutor = pluginExecutor;
|
||||
this.callback = callback;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public SimplexTransportReader createReader(ContactId c) {
|
||||
@@ -72,7 +74,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
||||
long capacity = getCapacity(dir.getPath());
|
||||
if(capacity < MIN_CONNECTION_LENGTH) return null;
|
||||
OutputStream out = new FileOutputStream(f);
|
||||
return new FileTransportWriter(f, out, capacity, this);
|
||||
return new FileTransportWriter(f, out, capacity, maxLatency, this);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
f.delete();
|
||||
|
||||
@@ -16,14 +16,15 @@ class FileTransportWriter implements SimplexTransportWriter {
|
||||
|
||||
private final File file;
|
||||
private final OutputStream out;
|
||||
private final long capacity;
|
||||
private final long capacity, maxLatency;
|
||||
private final FilePlugin plugin;
|
||||
|
||||
FileTransportWriter(File file, OutputStream out, long capacity,
|
||||
FilePlugin plugin) {
|
||||
long maxLatency, FilePlugin plugin) {
|
||||
this.file = file;
|
||||
this.out = out;
|
||||
this.capacity = capacity;
|
||||
this.maxLatency = maxLatency;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@@ -31,6 +32,10 @@ class FileTransportWriter implements SimplexTransportWriter {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -31,15 +31,13 @@ implements RemovableDriveMonitor.Callback {
|
||||
|
||||
private final RemovableDriveFinder finder;
|
||||
private final RemovableDriveMonitor monitor;
|
||||
private final long maxLatency;
|
||||
|
||||
RemovableDrivePlugin(@PluginExecutor Executor pluginExecutor,
|
||||
SimplexPluginCallback callback, RemovableDriveFinder finder,
|
||||
RemovableDriveMonitor monitor, long maxLatency) {
|
||||
super(pluginExecutor, callback);
|
||||
super(pluginExecutor, callback, maxLatency);
|
||||
this.finder = finder;
|
||||
this.monitor = monitor;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public TransportId getId() {
|
||||
|
||||
@@ -234,6 +234,10 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
||||
|
||||
private final CountDownLatch finished = new CountDownLatch(1);
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return modem.getInputStream();
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
// Connect back on the advertised TCP port
|
||||
Socket s = new Socket(packet.getAddress(), port);
|
||||
s.setSoTimeout(0);
|
||||
return new TcpTransportConnection(s);
|
||||
return new TcpTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
@@ -290,7 +290,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
ss.setSoTimeout(wait < 1 ? 1 : wait);
|
||||
Socket s = ss.accept();
|
||||
s.setSoTimeout(0);
|
||||
return new TcpTransportConnection(s);
|
||||
return new TcpTransportConnection(s, maxLatency);
|
||||
} catch(SocketTimeoutException e) {
|
||||
now = clock.currentTimeMillis();
|
||||
if(now < end) {
|
||||
|
||||
@@ -131,8 +131,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
TcpTransportConnection conn = new TcpTransportConnection(s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
callback.incomingConnectionCreated(new TcpTransportConnection(s,
|
||||
maxLatency));
|
||||
if(!running) return;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
try {
|
||||
s.setSoTimeout(0);
|
||||
s.connect(addr);
|
||||
return new TcpTransportConnection(s);
|
||||
return new TcpTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
|
||||
return null;
|
||||
|
||||
@@ -10,9 +10,15 @@ import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
|
||||
class TcpTransportConnection implements DuplexTransportConnection {
|
||||
|
||||
private final Socket socket;
|
||||
private final long maxLatency;
|
||||
|
||||
TcpTransportConnection(Socket socket) {
|
||||
TcpTransportConnection(Socket socket, long maxLatency) {
|
||||
this.socket = socket;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
|
||||
@@ -195,8 +195,8 @@ class TorPlugin implements DuplexPlugin {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
TorTransportConnection conn = new TorTransportConnection(s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
callback.incomingConnectionCreated(new TorTransportConnection(s,
|
||||
maxLatency));
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
@@ -277,7 +277,7 @@ class TorPlugin implements DuplexPlugin {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Connecting to hidden service");
|
||||
NetSocket s = nl.createNetSocket(null, null, addr);
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Connected to hidden service");
|
||||
return new TorTransportConnection(s);
|
||||
return new TorTransportConnection(s, maxLatency);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
|
||||
return null;
|
||||
|
||||
@@ -11,9 +11,15 @@ import org.silvertunnel.netlib.api.NetSocket;
|
||||
class TorTransportConnection implements DuplexTransportConnection {
|
||||
|
||||
private final NetSocket socket;
|
||||
private final long maxLatency;
|
||||
|
||||
TorTransportConnection(NetSocket socket) {
|
||||
TorTransportConnection(NetSocket socket, long maxLatency) {
|
||||
this.socket = socket;
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
|
||||
@@ -503,12 +503,12 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.generateBatch(contactId, 123);
|
||||
db.generateBatch(contactId, 123, 456);
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
try {
|
||||
db.generateBatch(contactId, 123, Arrays.asList(messageId));
|
||||
db.generateBatch(contactId, 123, 456, Arrays.asList(messageId));
|
||||
fail();
|
||||
} catch(NoSuchContactException expected) {}
|
||||
|
||||
@@ -696,14 +696,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).getRawMessage(txn, messageId1);
|
||||
will(returnValue(raw1));
|
||||
// Record the outstanding messages
|
||||
// FIXME: Calculate the expiry time
|
||||
oneOf(database).addOutstandingMessages(txn, contactId, sendable,
|
||||
Long.MAX_VALUE);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
|
||||
assertEquals(messages, db.generateBatch(contactId, size * 2));
|
||||
assertEquals(messages, db.generateBatch(contactId, size * 2,
|
||||
Long.MAX_VALUE));
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
@@ -733,16 +733,15 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
will(returnValue(raw1)); // Message is sendable
|
||||
oneOf(database).getRawMessageIfSendable(txn, contactId, messageId2);
|
||||
will(returnValue(null)); // Message is not sendable
|
||||
// Record the outstanding messages
|
||||
// FIXME: Calculate the expiry time
|
||||
// Record the outstanding message
|
||||
oneOf(database).addOutstandingMessages(txn, contactId,
|
||||
Collections.singletonList(messageId1), Long.MAX_VALUE);
|
||||
Arrays.asList(messageId1), Long.MAX_VALUE);
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
|
||||
assertEquals(messages, db.generateBatch(contactId, size * 3,
|
||||
requested));
|
||||
Long.MAX_VALUE, requested));
|
||||
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@@ -524,9 +524,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(messageId, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
// FIXME: Calculate the expiry time
|
||||
db.addOutstandingMessages(txn, contactId,
|
||||
Collections.singletonList(messageId), Long.MAX_VALUE);
|
||||
db.addOutstandingMessages(txn, contactId, Arrays.asList(messageId),
|
||||
Long.MAX_VALUE);
|
||||
|
||||
// The message should no longer be sendable
|
||||
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
||||
|
||||
@@ -87,7 +87,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
public void testConnectionTooShort() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, MAX_PACKET_LENGTH, true);
|
||||
out, MAX_PACKET_LENGTH, Long.MAX_VALUE, true);
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
secret, 0, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
@@ -105,7 +105,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
public void testNothingToSend() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, MIN_CONNECTION_LENGTH, true);
|
||||
out, MIN_CONNECTION_LENGTH, Long.MAX_VALUE, true);
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
secret, 0, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
@@ -134,7 +134,8 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
oneOf(db).generateAck(with(contactId), with(any(int.class)));
|
||||
will(returnValue(null));
|
||||
// No messages to send
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(any(long.class)));
|
||||
will(returnValue(null));
|
||||
}});
|
||||
connection.write();
|
||||
@@ -150,7 +151,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
public void testSomethingToSend() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, MIN_CONNECTION_LENGTH, true);
|
||||
out, MIN_CONNECTION_LENGTH, Long.MAX_VALUE, true);
|
||||
ConnectionContext ctx = new ConnectionContext(contactId, transportId,
|
||||
secret, 0, true);
|
||||
OutgoingSimplexConnection connection = new OutgoingSimplexConnection(db,
|
||||
@@ -183,10 +184,12 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
|
||||
oneOf(db).generateAck(with(contactId), with(any(int.class)));
|
||||
will(returnValue(null));
|
||||
// One message to send
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(any(long.class)));
|
||||
will(returnValue(Collections.singletonList(raw)));
|
||||
// No more messages
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)));
|
||||
oneOf(db).generateBatch(with(contactId), with(any(int.class)),
|
||||
with(any(long.class)));
|
||||
will(returnValue(null));
|
||||
}});
|
||||
connection.write();
|
||||
|
||||
@@ -126,7 +126,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
PacketWriterFactory packetWriterFactory =
|
||||
alice.getInstance(PacketWriterFactory.class);
|
||||
TestSimplexTransportWriter transport = new TestSimplexTransportWriter(
|
||||
out, Long.MAX_VALUE, false);
|
||||
out, Long.MAX_VALUE, Long.MAX_VALUE, false);
|
||||
ConnectionContext ctx = km.getConnectionContext(contactId, transportId);
|
||||
assertNotNull(ctx);
|
||||
OutgoingSimplexConnection simplex = new OutgoingSimplexConnection(db,
|
||||
|
||||
@@ -8,15 +8,16 @@ import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
|
||||
class TestSimplexTransportWriter implements SimplexTransportWriter {
|
||||
|
||||
private final ByteArrayOutputStream out;
|
||||
private final long capacity;
|
||||
private final long capacity, maxLatency;
|
||||
private final boolean flush;
|
||||
|
||||
private boolean disposed = false, exception = false;
|
||||
|
||||
TestSimplexTransportWriter(ByteArrayOutputStream out, long capacity,
|
||||
boolean flush) {
|
||||
long maxLatency, boolean flush) {
|
||||
this.out = out;
|
||||
this.capacity = capacity;
|
||||
this.maxLatency = maxLatency;
|
||||
this.flush = flush;
|
||||
}
|
||||
|
||||
@@ -24,6 +25,10 @@ class TestSimplexTransportWriter implements SimplexTransportWriter {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public long getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user