From f08e3a58e6c5775e5ee14d40e96ae6efb99b3be1 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 17 Apr 2019 12:44:43 +0100 Subject: [PATCH] Add database methods for pending contacts. --- .../bramble/api/contact/PendingContact.java | 11 +- .../api/contact/PendingContactState.java | 30 +++++ .../PendingContactStateChangedEvent.java | 2 +- .../bramble/contact/ContactManagerImpl.java | 2 +- .../org/briarproject/bramble/db/Database.java | 25 +++++ .../briarproject/bramble/db/JdbcDatabase.java | 104 +++++++++++++++++- .../bramble/db/Migration41_42.java | 3 + 7 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContactState.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java index 025803026..7b77cd805 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java @@ -8,13 +8,6 @@ import javax.annotation.concurrent.Immutable; @NotNullByDefault public class PendingContact { - public enum PendingContactState { - WAITING_FOR_CONNECTION, - CONNECTED, - ADDING_CONTACT, - FAILED - } - private final PendingContactId id; private final String alias; private final PendingContactState state; @@ -28,6 +21,10 @@ public class PendingContact { this.timestamp = timestamp; } + public PendingContactId getId() { + return id; + } + public String getAlias() { return alias; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContactState.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContactState.java new file mode 100644 index 000000000..5fd5a9919 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContactState.java @@ -0,0 +1,30 @@ +package org.briarproject.bramble.api.contact; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +public enum PendingContactState { + + WAITING_FOR_CONNECTION(0), + CONNECTED(1), + ADDING_CONTACT(2), + FAILED(3); + + private final int value; + + PendingContactState(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static PendingContactState fromValue(int value) { + for (PendingContactState s : values()) if (s.value == value) return s; + throw new IllegalArgumentException(); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/PendingContactStateChangedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/PendingContactStateChangedEvent.java index b5a8dc11a..6e7b454c3 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/PendingContactStateChangedEvent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/event/PendingContactStateChangedEvent.java @@ -1,7 +1,7 @@ package org.briarproject.bramble.api.contact.event; -import org.briarproject.bramble.api.contact.PendingContact.PendingContactState; import org.briarproject.bramble.api.contact.PendingContactId; +import org.briarproject.bramble.api.contact.PendingContactState; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java index 1bae6b16d..3d9c0790f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java @@ -30,7 +30,7 @@ import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; import static java.util.Collections.emptyList; -import static org.briarproject.bramble.api.contact.PendingContact.PendingContactState.WAITING_FOR_CONNECTION; +import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES; import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN; 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 6643419e0..a75094362 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 @@ -2,7 +2,9 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; +import org.briarproject.bramble.api.contact.PendingContactState; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; @@ -129,6 +131,11 @@ interface Database { */ void addOfferedMessage(T txn, ContactId c, MessageId m) throws DbException; + /** + * Stores a pending contact. + */ + void addPendingContact(T txn, PendingContact p) throws DbException; + /** * Stores the given static transport keys for the given contact and returns * a key set ID. @@ -497,6 +504,13 @@ interface Database { */ long getNextSendTime(T txn, ContactId c) throws DbException; + /** + * Returns all pending contacts. + *

+ * Read-only. + */ + Collection getPendingContacts(T txn) throws DbException; + /** * Returns the IDs of some messages that are eligible to be sent to the * given contact and have been requested by the contact, up to the given @@ -626,6 +640,11 @@ interface Database { void removeOfferedMessages(T txn, ContactId c, Collection requested) throws DbException; + /** + * Removes a pending contact (and all associated state) from the database. + */ + void removePendingContact(T txn, PendingContactId p) throws DbException; + /** * Removes the given static transport keys from the database. */ @@ -684,6 +703,12 @@ interface Database { void setMessageState(T txn, MessageId m, MessageState state) throws DbException; + /** + * Sets the state of the given pending contact. + */ + void setPendingContactState(T txn, PendingContactId p, + PendingContactState state) throws DbException; + /** * Sets the reordering window for the given key set and transport in the * given time period. 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 d38dfb101..440e025d1 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 @@ -2,7 +2,9 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; +import org.briarproject.bramble.api.contact.PendingContactState; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; @@ -289,6 +291,9 @@ abstract class JdbcDatabase implements Database { private static final String CREATE_PENDING_CONTACTS = "CREATE TABLE pendingContacts" + " (pendingContactId _HASH NOT NULL," + + " alias _STRING NOT NULL," + + " state INT NOT NULL," + + " timestamp BIGINT NOT NULL," + " PRIMARY KEY (pendingContactId))"; private static final String CREATE_OUTGOING_STATIC_KEYS = @@ -947,6 +952,28 @@ abstract class JdbcDatabase implements Database { } } + @Override + public void addPendingContact(Connection txn, PendingContact p) + throws DbException { + PreparedStatement ps = null; + try { + String sql = "INSERT INTO pendingContacts (pendingContactId," + + " alias, state, timestamp)" + + " VALUES (?, ?, ?, ?)"; + ps = txn.prepareStatement(sql); + ps.setBytes(1, p.getId().getBytes()); + ps.setString(2, p.getAlias()); + ps.setInt(3, p.getState().getValue()); + ps.setLong(4, p.getTimestamp()); + int affected = ps.executeUpdate(); + if (affected != 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public StaticTransportKeySetId addStaticTransportKeys(Connection txn, ContactId c, StaticTransportKeys k) throws DbException { @@ -1428,14 +1455,14 @@ abstract class JdbcDatabase implements Database { @Override public Collection getContacts(Connection txn) throws DbException { - PreparedStatement ps = null; + Statement s = null; ResultSet rs = null; try { String sql = "SELECT contactId, authorId, formatVersion, name," + " alias, publicKey, localAuthorId, verified, active" + " FROM contacts"; - ps = txn.prepareStatement(sql); - rs = ps.executeQuery(); + s = txn.createStatement(); + rs = s.executeQuery(sql); List contacts = new ArrayList<>(); while (rs.next()) { ContactId contactId = new ContactId(rs.getInt(1)); @@ -1453,11 +1480,11 @@ abstract class JdbcDatabase implements Database { alias, verified, active)); } rs.close(); - ps.close(); + s.close(); return contacts; } catch (SQLException e) { tryToClose(rs, LOG, WARNING); - tryToClose(ps, LOG, WARNING); + tryToClose(s, LOG, WARNING); throw new DbException(e); } } @@ -2258,6 +2285,36 @@ abstract class JdbcDatabase implements Database { } } + @Override + public Collection getPendingContacts(Connection txn) + throws DbException { + Statement s = null; + ResultSet rs = null; + try { + String sql = "SELECT pendingContactId, alias, state, timestamp" + + " FROM pendingContacts"; + s = txn.createStatement(); + rs = s.executeQuery(sql); + List pendingContacts = new ArrayList<>(); + while (rs.next()) { + PendingContactId id = new PendingContactId(rs.getBytes(1)); + String alias = rs.getString(2); + PendingContactState state = + PendingContactState.fromValue(rs.getInt(3)); + long timestamp = rs.getLong(4); + pendingContacts.add(new PendingContact(id, alias, state, + timestamp)); + } + rs.close(); + s.close(); + return pendingContacts; + } catch (SQLException e) { + tryToClose(rs, LOG, WARNING); + tryToClose(s, LOG, WARNING); + throw new DbException(e); + } + } + @Override public Collection getRequestedMessagesToSend(Connection txn, ContactId c, int maxLength, int maxLatency) throws DbException { @@ -2949,6 +3006,24 @@ abstract class JdbcDatabase implements Database { } } + @Override + public void removePendingContact(Connection txn, PendingContactId p) + throws DbException { + PreparedStatement ps = null; + try { + String sql = "DELETE FROM pendingContacts" + + " WHERE pendingContactId = ?"; + ps = txn.prepareStatement(sql); + ps.setBytes(1, p.getBytes()); + int affected = ps.executeUpdate(); + if (affected != 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public void removeStaticTransportKeys(Connection txn, TransportId t, StaticTransportKeySetId k) throws DbException { @@ -3198,6 +3273,25 @@ abstract class JdbcDatabase implements Database { } } + @Override + public void setPendingContactState(Connection txn, PendingContactId p, + PendingContactState state) throws DbException { + PreparedStatement ps = null; + try { + String sql = "UPDATE pendingContacts SET state = ?" + + " WHERE pendingContactId = ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, state.getValue()); + ps.setBytes(2, p.getBytes()); + int affected = ps.executeUpdate(); + if (affected != 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public void setReorderingWindow(Connection txn, TransportKeySetId k, TransportId t, long timePeriod, long base, byte[] bitmap) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration41_42.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration41_42.java index a10592793..9dd523e4f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration41_42.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration41_42.java @@ -46,6 +46,9 @@ class Migration41_42 implements Migration { + " DROP COLUMN contactId"); s.execute(dbTypes.replaceTypes("CREATE TABLE pendingContacts" + " (pendingContactId _HASH NOT NULL," + + " alias _STRING NOT NULL," + + " state INT NOT NULL," + + " timestamp BIGINT NOT NULL," + " PRIMARY KEY (pendingContactId))")); s.execute(dbTypes.replaceTypes("CREATE TABLE outgoingStaticKeys" + " (transportId _STRING NOT NULL,"