mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-06-15 12:00:57 +02:00
Add a method for checking whether we can send streams.
This commit is contained in:
@@ -57,6 +57,12 @@ public interface KeyManager {
|
|||||||
void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if we have keys that can be used for outgoing streams to
|
||||||
|
* the given contact over the given transport.
|
||||||
|
*/
|
||||||
|
boolean canSendOutgoingStreams(ContactId c, TransportId t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link StreamContext} for sending a stream to the given
|
* Returns a {@link StreamContext} for sending a stream to the given
|
||||||
* contact over the given transport, or null if an error occurs or the
|
* contact over the given transport, or null if an error occurs or the
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSendOutgoingStreams(ContactId c, TransportId t) {
|
||||||
|
TransportKeyManager m = managers.get(t);
|
||||||
|
return m == null ? false : m.canSendOutgoingStreams(c);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamContext getStreamContext(ContactId c, TransportId t)
|
public StreamContext getStreamContext(ContactId c, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ interface TransportKeyManager {
|
|||||||
|
|
||||||
void removeContact(ContactId c);
|
void removeContact(ContactId c);
|
||||||
|
|
||||||
|
boolean canSendOutgoingStreams(ContactId c);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
StreamContext getStreamContext(Transaction txn, ContactId c)
|
StreamContext getStreamContext(Transaction txn, ContactId c)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|||||||
+15
@@ -278,6 +278,21 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSendOutgoingStreams(ContactId c) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
MutableKeySet ks = outContexts.get(c);
|
||||||
|
if (ks == null) return false;
|
||||||
|
MutableOutgoingKeys outKeys =
|
||||||
|
ks.getTransportKeys().getCurrentOutgoingKeys();
|
||||||
|
if (!outKeys.isActive()) throw new AssertionError();
|
||||||
|
return outKeys.getStreamCounter() <= MAX_32_BIT_UNSIGNED;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamContext getStreamContext(Transaction txn, ContactId c)
|
public StreamContext getStreamContext(Transaction txn, ContactId c)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
|
|||||||
+24
-15
@@ -30,6 +30,7 @@ import java.util.concurrent.Executor;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
@@ -37,8 +38,10 @@ import static org.briarproject.bramble.api.transport.TransportConstants.REORDERI
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
@@ -112,6 +115,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
transportKeyManager.start(txn);
|
transportKeyManager.start(txn);
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -150,6 +154,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000 - 1;
|
long timestamp = rotationPeriodLength * 1000 - 1;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
||||||
alice);
|
alice);
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -181,6 +186,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000 - 1;
|
long timestamp = rotationPeriodLength * 1000 - 1;
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
||||||
masterKey, timestamp, alice));
|
masterKey, timestamp, alice));
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -192,6 +198,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -212,6 +219,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
||||||
alice);
|
alice);
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +246,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
||||||
alice);
|
alice);
|
||||||
// The first request should return a stream context
|
// The first request should return a stream context
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
||||||
contactId);
|
contactId);
|
||||||
assertNotNull(ctx);
|
assertNotNull(ctx);
|
||||||
@@ -247,6 +256,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(headerKey, ctx.getHeaderKey());
|
assertEquals(headerKey, ctx.getHeaderKey());
|
||||||
assertEquals(MAX_32_BIT_UNSIGNED, ctx.getStreamNumber());
|
assertEquals(MAX_32_BIT_UNSIGNED, ctx.getStreamNumber());
|
||||||
// The second request should return null, the counter is exhausted
|
// The second request should return null, the counter is exhausted
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,6 +276,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
||||||
alice);
|
alice);
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
// The tag should not be recognised
|
// The tag should not be recognised
|
||||||
assertNull(transportKeyManager.getStreamContext(txn,
|
assertNull(transportKeyManager.getStreamContext(txn,
|
||||||
new byte[TAG_LENGTH]));
|
new byte[TAG_LENGTH]));
|
||||||
@@ -316,6 +327,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
transportKeyManager.addContact(txn, contactId, masterKey, timestamp,
|
||||||
alice);
|
alice);
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
// Use the first tag (previous rotation period, stream number 0)
|
// Use the first tag (previous rotation period, stream number 0)
|
||||||
assertEquals(REORDERING_WINDOW_SIZE * 3, tags.size());
|
assertEquals(REORDERING_WINDOW_SIZE * 3, tags.size());
|
||||||
byte[] tag = tags.get(0);
|
byte[] tag = tags.get(0);
|
||||||
@@ -336,13 +348,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testKeysAreRotatedToCurrentPeriod() throws Exception {
|
public void testKeysAreRotatedToCurrentPeriod() throws Exception {
|
||||||
TransportKeys transportKeys = createTransportKeys(1000, 0, true);
|
TransportKeys transportKeys = createTransportKeys(1000, 0, true);
|
||||||
TransportKeys transportKeys1 = createTransportKeys(1000, 0, false);
|
Collection<KeySet> loaded =
|
||||||
Collection<KeySet> loaded = asList(
|
singletonList(new KeySet(keySetId, contactId, transportKeys));
|
||||||
new KeySet(keySetId, contactId, transportKeys),
|
|
||||||
new KeySet(keySetId1, null, transportKeys1)
|
|
||||||
);
|
|
||||||
TransportKeys rotated = createTransportKeys(1001, 0, true);
|
TransportKeys rotated = createTransportKeys(1001, 0, true);
|
||||||
TransportKeys rotated1 = createTransportKeys(1001, 0, false);
|
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
|
|
||||||
@@ -356,8 +364,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
// Rotate the transport keys (the keys are unaffected)
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
oneOf(transportCrypto).rotateTransportKeys(transportKeys, 1000);
|
oneOf(transportCrypto).rotateTransportKeys(transportKeys, 1000);
|
||||||
will(returnValue(transportKeys));
|
will(returnValue(transportKeys));
|
||||||
oneOf(transportCrypto).rotateTransportKeys(transportKeys1, 1000);
|
|
||||||
will(returnValue(transportKeys1));
|
|
||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(transportCrypto).encodeTag(
|
exactly(3).of(transportCrypto).encodeTag(
|
||||||
@@ -381,9 +387,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(transportCrypto).rotateTransportKeys(
|
oneOf(transportCrypto).rotateTransportKeys(
|
||||||
with(any(TransportKeys.class)), with(1001L));
|
with(any(TransportKeys.class)), with(1001L));
|
||||||
will(returnValue(rotated));
|
will(returnValue(rotated));
|
||||||
oneOf(transportCrypto).rotateTransportKeys(
|
|
||||||
with(any(TransportKeys.class)), with(1001L));
|
|
||||||
will(returnValue(rotated1));
|
|
||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(transportCrypto).encodeTag(
|
exactly(3).of(transportCrypto).encodeTag(
|
||||||
@@ -392,10 +395,8 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Save the keys that were rotated
|
// Save the keys that were rotated
|
||||||
oneOf(db).updateTransportKeys(txn1, asList(
|
oneOf(db).updateTransportKeys(txn1,
|
||||||
new KeySet(keySetId1, null, rotated1),
|
singletonList(new KeySet(keySetId, contactId, rotated)));
|
||||||
new KeySet(keySetId, contactId, rotated)
|
|
||||||
));
|
|
||||||
// Schedule key rotation at the start of the next rotation period
|
// Schedule key rotation at the start of the next rotation period
|
||||||
oneOf(scheduler).schedule(with(any(Runnable.class)),
|
oneOf(scheduler).schedule(with(any(Runnable.class)),
|
||||||
with(rotationPeriodLength), with(MILLISECONDS));
|
with(rotationPeriodLength), with(MILLISECONDS));
|
||||||
@@ -408,6 +409,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
db, transportCrypto, dbExecutor, scheduler, clock, transportId,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
transportKeyManager.start(txn);
|
transportKeyManager.start(txn);
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -451,11 +453,16 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
||||||
masterKey, timestamp, alice));
|
masterKey, timestamp, alice));
|
||||||
|
// The keys are unbound so no stream context should be returned
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
transportKeyManager.bindKeys(txn, contactId, keySetId);
|
transportKeyManager.bindKeys(txn, contactId, keySetId);
|
||||||
// The keys are inactive so no stream context should be returned
|
// The keys are inactive so no stream context should be returned
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
assertNull(transportKeyManager.getStreamContext(txn, contactId));
|
||||||
transportKeyManager.activateKeys(txn, keySetId);
|
transportKeyManager.activateKeys(txn, keySetId);
|
||||||
// The keys are active so a stream context should be returned
|
// The keys are active so a stream context should be returned
|
||||||
|
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
StreamContext ctx = transportKeyManager.getStreamContext(txn,
|
||||||
contactId);
|
contactId);
|
||||||
assertNotNull(ctx);
|
assertNotNull(ctx);
|
||||||
@@ -496,7 +503,9 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timestamp = rotationPeriodLength * 1000;
|
long timestamp = rotationPeriodLength * 1000;
|
||||||
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn,
|
||||||
masterKey, timestamp, alice));
|
masterKey, timestamp, alice));
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
transportKeyManager.removeKeys(txn, keySetId);
|
transportKeyManager.removeKeys(txn, keySetId);
|
||||||
|
assertFalse(transportKeyManager.canSendOutgoingStreams(contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectAddContactNoRotation(boolean alice,
|
private void expectAddContactNoRotation(boolean alice,
|
||||||
|
|||||||
Reference in New Issue
Block a user