diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 2a4f262de853052e12b216ec8d008dd1ad81c475..fcf5efe46c8b58bf47b1776f7588f620b60aab08 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -481,6 +481,12 @@ public interface DatabaseComponent { */ void removeTransport(Transaction txn, TransportId t) throws DbException; + /** + * Removes the given transport keys from the database. + */ + void removeTransportKeys(Transaction txn, TransportId t, KeySetId k) + throws DbException; + /** * Marks the given contact as verified. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java index 50a5cf9480c430d8eb876fdb67642f86a2c30282..06b2f472587b0e2004696e47bafa22c0ac79b60e 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java @@ -40,6 +40,13 @@ public interface KeyManager { void bindKeys(Transaction txn, ContactId c, Map<TransportId, KeySetId> keys) throws DbException; + /** + * Removes the given transport keys, which must not have been bound, from + * the manager and the database. + */ + void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys) + throws DbException; + /** * Returns a {@link StreamContext} for sending a stream to the given * contact over the given transport, or null if an error occurs or the diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index b11e1b828118593e3d1052f4c2c512c5c309c384..6ee996b2b8eedd8d4812005ae62eb5dc30a7e5ea 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -593,6 +593,12 @@ interface Database<T> { */ void removeTransport(T txn, TransportId t) throws DbException; + /** + * Removes the given transport keys from the database. + */ + void removeTransportKeys(T txn, TransportId t, KeySetId k) + throws DbException; + /** * Resets the transmission count and expiry time of the given message with * respect to the given contact. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 305b672900fa61c8dc2cb10759f198c95f9c5b0c..697bcdd3d66adc7595002d2b5591101786c5e261 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -791,6 +791,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { db.removeTransport(txn, t); } + @Override + public void removeTransportKeys(Transaction transaction, + TransportId t, KeySetId k) throws DbException { + if (transaction.isReadOnly()) throw new IllegalArgumentException(); + T txn = unbox(transaction); + if (!db.containsTransport(txn, t)) + throw new NoSuchTransportException(); + db.removeTransportKeys(txn, t, k); + } + @Override public void setContactVerified(Transaction transaction, ContactId c) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index 747145a3442087ffc2d6b22e203b07e666fcdf59..25cfb4d5aa5aa0177360d8b8d03532438eddb542 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -2681,6 +2681,27 @@ abstract class JdbcDatabase implements Database<Connection> { } } + @Override + public void removeTransportKeys(Connection txn, TransportId t, KeySetId k) + throws DbException { + PreparedStatement ps = null; + try { + // Delete any existing outgoing keys - this will also remove any + // incoming keys with the same key set ID + String sql = "DELETE FROM outgoingKeys" + + " WHERE transportId = ? AND keySetId = ?"; + ps = txn.prepareStatement(sql); + ps.setString(1, t.getString()); + ps.setInt(2, k.getInt()); + int affected = ps.executeUpdate(); + if (affected < 0) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps); + throw new DbException(e); + } + } + @Override public void resetExpiryTime(Connection txn, ContactId c, MessageId m) throws DbException { @@ -2905,30 +2926,10 @@ abstract class JdbcDatabase implements Database<Connection> { @Override public void updateTransportKeys(Connection txn, Collection<KeySet> keys) throws DbException { - PreparedStatement ps = null; - try { - // Delete any existing outgoing keys - this will also remove any - // incoming keys with the same key set ID - // TODO: Add an index to speed this up? - String sql = "DELETE FROM outgoingKeys WHERE keySetId = ?"; - ps = txn.prepareStatement(sql); - for (KeySet ks : keys) { - ps.setInt(1, ks.getKeySetId().getInt()); - ps.addBatch(); - } - int[] batchAffected = ps.executeBatch(); - if (batchAffected.length != keys.size()) - throw new DbStateException(); - for (int rows: batchAffected) - if (rows < 0) throw new DbStateException(); - ps.close(); - } catch (SQLException e) { - tryToClose(ps); - throw new DbException(e); - } - // Store the new keys for (KeySet ks : keys) { - addTransportKeys(txn, ks.getContactId(), ks.getTransportKeys()); + TransportKeys k = ks.getTransportKeys(); + removeTransportKeys(txn, k.getTransportId(), ks.getKeySetId()); + addTransportKeys(txn, ks.getContactId(), k); } } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java index c07c9e1e72ee6f48ecade12704b2f52e474396ec..1a06ef4a6503819f7c2761a8062d5531b419a8bc 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java @@ -132,6 +132,20 @@ class KeyManagerImpl implements KeyManager, Service, EventListener { } } + @Override + public void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys) + throws DbException { + for (Entry<TransportId, KeySetId> e : keys.entrySet()) { + TransportId t = e.getKey(); + TransportKeyManager m = managers.get(t); + if (m == null) { + if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t); + } else { + m.removeKeys(txn, e.getValue()); + } + } + } + @Override public StreamContext getStreamContext(ContactId c, TransportId t) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java index 41e31fbe62e2abb8727541fd1ffecc25f517fd4a..4eff0b289d4043715a18abfb27911619487b7c6e 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java @@ -23,6 +23,8 @@ interface TransportKeyManager { void bindKeys(Transaction txn, ContactId c, KeySetId k) throws DbException; + void removeKeys(Transaction txn, KeySetId k) throws DbException; + void removeContact(ContactId c); @Nullable diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java index 6b9a1519ebe7ef4fbba42bb2d0e2500c0dd9c967..889485d0dc34795bda559dcce63020613e11cf67 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java @@ -219,6 +219,20 @@ class TransportKeyManagerImpl implements TransportKeyManager { } } + @Override + public void removeKeys(Transaction txn, KeySetId k) throws DbException { + lock.lock(); + try { + MutableKeySet ks = keys.remove(k); + if (ks == null) throw new IllegalArgumentException(); + if (ks.getContactId() != null) throw new IllegalArgumentException(); + TransportId t = ks.getTransportKeys().getTransportId(); + db.removeTransportKeys(txn, t, k); + } finally { + lock.unlock(); + } + } + @Override public void removeContact(ContactId c) { lock.lock();