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 e5be04b55..563ce2d8e 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
@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.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.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author;
@@ -137,6 +138,12 @@ public interface DatabaseComponent {
void addLocalMessage(Transaction txn, Message m, Metadata meta,
boolean shared) throws DbException;
+ /**
+ * Stores a pending contact.
+ */
+ void addPendingContact(Transaction txn, PendingContact p)
+ throws DbException;
+
/**
* Stores a transport.
*/
@@ -153,21 +160,35 @@ public interface DatabaseComponent {
/**
* Returns true if the database contains the given contact for the given
* local pseudonym.
+ *
+ * Read-only.
*/
boolean containsContact(Transaction txn, AuthorId remote, AuthorId local)
throws DbException;
/**
* Returns true if the database contains the given group.
+ *
+ * Read-only.
*/
boolean containsGroup(Transaction txn, GroupId g) throws DbException;
/**
* Returns true if the database contains the given local author.
+ *
+ * Read-only.
*/
boolean containsLocalAuthor(Transaction txn, AuthorId local)
throws DbException;
+ /**
+ * Returns true if the database contains the given pending contact.
+ *
+ * Read-only.
+ */
+ boolean containsPendingContact(Transaction txn, PendingContactId p)
+ throws DbException;
+
/**
* Deletes the message with the given ID. Unlike
* {@link #removeMessage(Transaction, MessageId)}, the message ID,
@@ -292,8 +313,8 @@ public interface DatabaseComponent {
*
* Read-only.
*/
- Collection getHandshakeKeys(Transaction txn,
- TransportId t) throws DbException;
+ Collection getHandshakeKeys(Transaction txn, TransportId t)
+ throws DbException;
/**
* Returns the local pseudonym with the given ID.
@@ -443,6 +464,14 @@ public interface DatabaseComponent {
*/
long getNextSendTime(Transaction txn, ContactId c) throws DbException;
+ /**
+ * Returns all pending contacts.
+ *
+ * Read-only.
+ */
+ Collection getPendingContacts(Transaction txn)
+ throws DbException;
+
/**
* Returns all settings in the given namespace.
*
@@ -539,6 +568,12 @@ public interface DatabaseComponent {
*/
void removeMessage(Transaction txn, MessageId m) throws DbException;
+ /**
+ * Removes a pending contact (and all associated state) from the database.
+ */
+ void removePendingContact(Transaction txn, PendingContactId p)
+ throws DbException;
+
/**
* Removes a transport (and all associated state) from the database.
*/
@@ -591,13 +626,21 @@ public interface DatabaseComponent {
Collection dependencies) throws DbException;
/**
- * Sets the reordering window for the given key set and transport in the
- * given time period.
+ * Sets the reordering window for the given transport key set in the given
+ * time period.
*/
void setReorderingWindow(Transaction txn, TransportKeySetId k,
TransportId t, long timePeriod, long base, byte[] bitmap)
throws DbException;
+ /**
+ * Sets the reordering window for the given handshake key set in the given
+ * time period.
+ */
+ void setReorderingWindow(Transaction txn, HandshakeKeySetId k,
+ TransportId t, long timePeriod, long base, byte[] bitmap)
+ throws DbException;
+
/**
* Marks the given transport keys as usable for outgoing streams.
*/
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchPendingContactException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchPendingContactException.java
new file mode 100644
index 000000000..d620e6d36
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchPendingContactException.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.db;
+
+/**
+ * Thrown when a database operation is attempted for a pending contact that is
+ * not in the database. This exception may occur due to concurrent updates and
+ * does not indicate a database error.
+ */
+public class NoSuchPendingContactException extends DbException {
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java
new file mode 100644
index 000000000..cefca3f0a
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/PendingContactExistsException.java
@@ -0,0 +1,9 @@
+package org.briarproject.bramble.api.db;
+
+/**
+ * Thrown when a duplicate pending contact is added to the database. This
+ * exception may occur due to concurrent updates and does not indicate a
+ * database error.
+ */
+public class PendingContactExistsException extends DbException {
+}
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 a70d1ca6b..b92ab8660 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
@@ -2,6 +2,7 @@ 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.event.ContactAddedEvent;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
@@ -22,8 +23,10 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
import org.briarproject.bramble.api.db.NoSuchMessageException;
+import org.briarproject.bramble.api.db.NoSuchPendingContactException;
import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.db.NullableDbCallable;
+import org.briarproject.bramble.api.db.PendingContactExistsException;
import org.briarproject.bramble.api.db.TaskAction;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
@@ -275,7 +278,7 @@ class DatabaseComponentImpl implements DatabaseComponent {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsPendingContact(txn, p))
- throw new NoSuchContactException();
+ throw new NoSuchPendingContactException();
if (!db.containsTransport(txn, k.getTransportId()))
throw new NoSuchTransportException();
return db.addHandshakeKeys(txn, p, k);
@@ -309,6 +312,16 @@ class DatabaseComponentImpl implements DatabaseComponent {
db.mergeMessageMetadata(txn, m.getId(), meta);
}
+ @Override
+ public void addPendingContact(Transaction transaction, PendingContact p)
+ throws DbException {
+ if (transaction.isReadOnly()) throw new IllegalArgumentException();
+ T txn = unbox(transaction);
+ if (db.containsPendingContact(txn, p.getId()))
+ throw new PendingContactExistsException();
+ db.addPendingContact(txn, p);
+ }
+
@Override
public void addTransport(Transaction transaction, TransportId t,
int maxLatency) throws DbException {
@@ -353,6 +366,13 @@ class DatabaseComponentImpl implements DatabaseComponent {
return db.containsLocalAuthor(txn, local);
}
+ @Override
+ public boolean containsPendingContact(Transaction transaction,
+ PendingContactId p) throws DbException {
+ T txn = unbox(transaction);
+ return db.containsPendingContact(txn, p);
+ }
+
@Override
public void deleteMessage(Transaction transaction, MessageId m)
throws DbException {
@@ -692,6 +712,13 @@ class DatabaseComponentImpl implements DatabaseComponent {
return db.getNextSendTime(txn, c);
}
+ @Override
+ public Collection getPendingContacts(
+ Transaction transaction) throws DbException {
+ T txn = unbox(transaction);
+ return db.getPendingContacts(txn);
+ }
+
@Override
public Settings getSettings(Transaction transaction, String namespace)
throws DbException {
@@ -709,9 +736,13 @@ class DatabaseComponentImpl implements DatabaseComponent {
}
@Override
- public void incrementStreamCounter(Transaction txn, TransportId t,
+ public void incrementStreamCounter(Transaction transaction, TransportId t,
HandshakeKeySetId k) throws DbException {
- // TODO
+ if (transaction.isReadOnly()) throw new IllegalArgumentException();
+ T txn = unbox(transaction);
+ if (!db.containsTransport(txn, t))
+ throw new NoSuchTransportException();
+ db.incrementStreamCounter(txn, t, k);
}
@Override
@@ -897,6 +928,16 @@ class DatabaseComponentImpl implements DatabaseComponent {
db.removeMessage(txn, m);
}
+ @Override
+ public void removePendingContact(Transaction transaction,
+ PendingContactId p) throws DbException {
+ if (transaction.isReadOnly()) throw new IllegalArgumentException();
+ T txn = unbox(transaction);
+ if (!db.containsPendingContact(txn, p))
+ throw new NoSuchPendingContactException();
+ db.removePendingContact(txn, p);
+ }
+
@Override
public void removeTransport(Transaction transaction, TransportId t)
throws DbException {
@@ -1018,6 +1059,17 @@ class DatabaseComponentImpl implements DatabaseComponent {
db.setReorderingWindow(txn, k, t, timePeriod, base, bitmap);
}
+ @Override
+ public void setReorderingWindow(Transaction transaction,
+ HandshakeKeySetId k, TransportId t, long timePeriod, long base,
+ byte[] bitmap) throws DbException {
+ if (transaction.isReadOnly()) throw new IllegalArgumentException();
+ T txn = unbox(transaction);
+ if (!db.containsTransport(txn, t))
+ throw new NoSuchTransportException();
+ db.setReorderingWindow(txn, k, t, timePeriod, base, bitmap);
+ }
+
@Override
public void setTransportKeysActive(Transaction transaction, TransportId t,
TransportKeySetId k) throws DbException {