mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Add database methods for static keys.
This commit is contained in:
@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
@@ -20,6 +21,9 @@ import org.briarproject.bramble.api.sync.MessageStatus;
|
|||||||
import org.briarproject.bramble.api.sync.Offer;
|
import org.briarproject.bramble.api.sync.Offer;
|
||||||
import org.briarproject.bramble.api.sync.Request;
|
import org.briarproject.bramble.api.sync.Request;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySet;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySetId;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySet;
|
import org.briarproject.bramble.api.transport.TransportKeySet;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -119,6 +123,20 @@ public interface DatabaseComponent {
|
|||||||
void addLocalMessage(Transaction txn, Message m, Metadata meta,
|
void addLocalMessage(Transaction txn, Message m, Metadata meta,
|
||||||
boolean shared) throws DbException;
|
boolean shared) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given static transport keys for the given contact and returns
|
||||||
|
* a key set ID.
|
||||||
|
*/
|
||||||
|
StaticTransportKeySetId addStaticTransportKeys(Transaction txn, ContactId c,
|
||||||
|
StaticTransportKeys k) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given static transport keys for the given pending contact and
|
||||||
|
* returns a key set ID.
|
||||||
|
*/
|
||||||
|
StaticTransportKeySetId addStaticTransportKeys(Transaction txn,
|
||||||
|
PendingContactId p, StaticTransportKeys k) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a transport.
|
* Stores a transport.
|
||||||
*/
|
*/
|
||||||
@@ -424,6 +442,14 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
Settings getSettings(Transaction txn, String namespace) throws DbException;
|
Settings getSettings(Transaction txn, String namespace) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all static transport keys for the given transport.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
Collection<StaticTransportKeySet> getStaticTransportKeys(Transaction txn,
|
||||||
|
TransportId t) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all transport keys for the given transport.
|
* Returns all transport keys for the given transport.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -432,6 +458,13 @@ public interface DatabaseComponent {
|
|||||||
Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t)
|
Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the outgoing stream counter for the given static transport
|
||||||
|
* keys.
|
||||||
|
*/
|
||||||
|
void incrementStreamCounter(Transaction txn, TransportId t,
|
||||||
|
StaticTransportKeySetId k) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the outgoing stream counter for the given transport keys.
|
* Increments the outgoing stream counter for the given transport keys.
|
||||||
*/
|
*/
|
||||||
@@ -501,6 +534,12 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
void removeMessage(Transaction txn, MessageId m) throws DbException;
|
void removeMessage(Transaction txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given static transport keys from the database.
|
||||||
|
*/
|
||||||
|
void removeStaticTransportKeys(Transaction txn, TransportId t,
|
||||||
|
StaticTransportKeySetId k) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a transport (and all associated state) from the database.
|
* Removes a transport (and all associated state) from the database.
|
||||||
*/
|
*/
|
||||||
@@ -566,6 +605,13 @@ public interface DatabaseComponent {
|
|||||||
void setTransportKeysActive(Transaction txn, TransportId t,
|
void setTransportKeysActive(Transaction txn, TransportId t,
|
||||||
TransportKeySetId k) throws DbException;
|
TransportKeySetId k) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given static transport keys, deleting any keys they have
|
||||||
|
* replaced.
|
||||||
|
*/
|
||||||
|
void updateStaticTransportKeys(Transaction txn,
|
||||||
|
Collection<StaticTransportKeySet> keys) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given transport keys, deleting any keys they have replaced.
|
* Stores the given transport keys, deleting any keys they have replaced.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||||
@@ -24,6 +25,9 @@ import org.briarproject.bramble.api.sync.Message;
|
|||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySet;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySetId;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySet;
|
import org.briarproject.bramble.api.transport.TransportKeySet;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -36,7 +40,7 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A low-level interface to the database ({@link DatabaseComponent} provides a
|
* A low-level interface to the database ({@link DatabaseComponent} provides a
|
||||||
* high-level interface).
|
* high-level interface).
|
||||||
* <p>
|
* <p/>
|
||||||
* Most operations take a transaction argument, which is obtained by calling
|
* Most operations take a transaction argument, which is obtained by calling
|
||||||
* {@link #startTransaction()}. Every transaction must be terminated by calling
|
* {@link #startTransaction()}. Every transaction must be terminated by calling
|
||||||
* either {@link #abortTransaction(Object) abortTransaction(T)} or
|
* either {@link #abortTransaction(Object) abortTransaction(T)} or
|
||||||
@@ -125,6 +129,20 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void addOfferedMessage(T txn, ContactId c, MessageId m) throws DbException;
|
void addOfferedMessage(T txn, ContactId c, MessageId m) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given static transport keys for the given contact and returns
|
||||||
|
* a key set ID.
|
||||||
|
*/
|
||||||
|
StaticTransportKeySetId addStaticTransportKeys(T txn, ContactId c,
|
||||||
|
StaticTransportKeys k) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given static transport keys for the given pending contact and
|
||||||
|
* returns a key set ID.
|
||||||
|
*/
|
||||||
|
StaticTransportKeySetId addStaticTransportKeys(T txn, PendingContactId p,
|
||||||
|
StaticTransportKeys k) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a transport.
|
* Stores a transport.
|
||||||
*/
|
*/
|
||||||
@@ -175,6 +193,14 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
boolean containsMessage(T txn, MessageId m) throws DbException;
|
boolean containsMessage(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the database contains the given pending contact.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
boolean containsPendingContact(T txn, PendingContactId p)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given transport.
|
* Returns true if the database contains the given transport.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -488,6 +514,14 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Settings getSettings(T txn, String namespace) throws DbException;
|
Settings getSettings(T txn, String namespace) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all static transport keys for the given transport.
|
||||||
|
* <p/>
|
||||||
|
* Read-only.
|
||||||
|
*/
|
||||||
|
Collection<StaticTransportKeySet> getStaticTransportKeys(T txn,
|
||||||
|
TransportId t) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all transport keys for the given transport.
|
* Returns all transport keys for the given transport.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -496,6 +530,13 @@ interface Database<T> {
|
|||||||
Collection<TransportKeySet> getTransportKeys(T txn, TransportId t)
|
Collection<TransportKeySet> getTransportKeys(T txn, TransportId t)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the outgoing stream counter for the given static transport
|
||||||
|
* keys.
|
||||||
|
*/
|
||||||
|
void incrementStreamCounter(T txn, TransportId t, StaticTransportKeySetId k)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the outgoing stream counter for the given transport keys.
|
* Increments the outgoing stream counter for the given transport keys.
|
||||||
*/
|
*/
|
||||||
@@ -585,6 +626,12 @@ interface Database<T> {
|
|||||||
void removeOfferedMessages(T txn, ContactId c,
|
void removeOfferedMessages(T txn, ContactId c,
|
||||||
Collection<MessageId> requested) throws DbException;
|
Collection<MessageId> requested) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given static transport keys from the database.
|
||||||
|
*/
|
||||||
|
void removeStaticTransportKeys(T txn, TransportId t,
|
||||||
|
StaticTransportKeySetId k) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a transport (and all associated state) from the database.
|
* Removes a transport (and all associated state) from the database.
|
||||||
*/
|
*/
|
||||||
@@ -658,6 +705,12 @@ interface Database<T> {
|
|||||||
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, int maxLatency)
|
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, int maxLatency)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the given static transport keys following key rotation.
|
||||||
|
*/
|
||||||
|
void updateStaticTransportKeys(T txn, StaticTransportKeySet ks)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the given transport keys following key rotation.
|
* Updates the given transport keys following key rotation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
|
||||||
@@ -59,6 +60,9 @@ import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
|
|||||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
|
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySet;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySetId;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySet;
|
import org.briarproject.bramble.api.transport.TransportKeySet;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -281,6 +285,32 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
db.mergeMessageMetadata(txn, m.getId(), meta);
|
db.mergeMessageMetadata(txn, m.getId(), meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StaticTransportKeySetId addStaticTransportKeys(
|
||||||
|
Transaction transaction, ContactId c, StaticTransportKeys k)
|
||||||
|
throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsContact(txn, c))
|
||||||
|
throw new NoSuchContactException();
|
||||||
|
if (!db.containsTransport(txn, k.getTransportId()))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
|
return db.addStaticTransportKeys(txn, c, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StaticTransportKeySetId addStaticTransportKeys(
|
||||||
|
Transaction transaction, PendingContactId p,
|
||||||
|
StaticTransportKeys k) throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsPendingContact(txn, p))
|
||||||
|
throw new NoSuchContactException();
|
||||||
|
if (!db.containsTransport(txn, k.getTransportId()))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
|
return db.addStaticTransportKeys(txn, p, k);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTransport(Transaction transaction, TransportId t,
|
public void addTransport(Transaction transaction, TransportId t,
|
||||||
int maxLatency) throws DbException {
|
int maxLatency) throws DbException {
|
||||||
@@ -662,6 +692,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
return db.getSettings(txn, namespace);
|
return db.getSettings(txn, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<StaticTransportKeySet> getStaticTransportKeys(
|
||||||
|
Transaction transaction, TransportId t) throws DbException {
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
|
return db.getStaticTransportKeys(txn, t);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TransportKeySet> getTransportKeys(Transaction transaction,
|
public Collection<TransportKeySet> getTransportKeys(Transaction transaction,
|
||||||
TransportId t) throws DbException {
|
TransportId t) throws DbException {
|
||||||
@@ -671,6 +710,12 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
return db.getTransportKeys(txn, t);
|
return db.getTransportKeys(txn, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementStreamCounter(Transaction txn, TransportId t,
|
||||||
|
StaticTransportKeySetId k) throws DbException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incrementStreamCounter(Transaction transaction, TransportId t,
|
public void incrementStreamCounter(Transaction transaction, TransportId t,
|
||||||
TransportKeySetId k) throws DbException {
|
TransportKeySetId k) throws DbException {
|
||||||
@@ -844,6 +889,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
db.removeMessage(txn, m);
|
db.removeMessage(txn, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeStaticTransportKeys(Transaction transaction,
|
||||||
|
TransportId t, StaticTransportKeySetId k) throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
|
db.removeStaticTransportKeys(txn, t, k);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTransport(Transaction transaction, TransportId t)
|
public void removeTransport(Transaction transaction, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -975,6 +1030,18 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
db.setTransportKeysActive(txn, t, k);
|
db.setTransportKeysActive(txn, t, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStaticTransportKeys(Transaction transaction,
|
||||||
|
Collection<StaticTransportKeySet> keys) throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
for (StaticTransportKeySet ks : keys) {
|
||||||
|
TransportId t = ks.getKeys().getTransportId();
|
||||||
|
if (db.containsTransport(txn, t))
|
||||||
|
db.updateStaticTransportKeys(txn, ks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTransportKeys(Transaction transaction,
|
public void updateTransportKeys(Transaction transaction,
|
||||||
Collection<TransportKeySet> keys) throws DbException {
|
Collection<TransportKeySet> keys) throws DbException {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.contact.PendingContactId;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||||
@@ -28,6 +29,9 @@ import org.briarproject.bramble.api.sync.validation.MessageState;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySet;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeySetId;
|
||||||
|
import org.briarproject.bramble.api.transport.StaticTransportKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySet;
|
import org.briarproject.bramble.api.transport.TransportKeySet;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
import org.briarproject.bramble.api.transport.TransportKeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -55,6 +59,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static java.sql.Types.BINARY;
|
||||||
import static java.sql.Types.INTEGER;
|
import static java.sql.Types.INTEGER;
|
||||||
import static java.sql.Types.VARCHAR;
|
import static java.sql.Types.VARCHAR;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
@@ -283,23 +288,26 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
|
|
||||||
private static final String CREATE_PENDING_CONTACTS =
|
private static final String CREATE_PENDING_CONTACTS =
|
||||||
"CREATE TABLE pendingContacts"
|
"CREATE TABLE pendingContacts"
|
||||||
+ " (pendingContactId _HASH NOT NULL,"
|
+ " (pendingContactId _HASH NOT NULL,"
|
||||||
+ " PRIMARY KEY (pendingContactId))";
|
+ " PRIMARY KEY (pendingContactId))";
|
||||||
|
|
||||||
private static final String CREATE_OUTGOING_STATIC_KEYS =
|
private static final String CREATE_OUTGOING_STATIC_KEYS =
|
||||||
"CREATE TABLE outgoingStaticKeys"
|
"CREATE TABLE outgoingStaticKeys"
|
||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " staticKeySetId _COUNTER,"
|
+ " keySetId _COUNTER,"
|
||||||
+ " rootKey _SECRET NOT NULL,"
|
|
||||||
+ " timePeriod BIGINT NOT NULL,"
|
+ " timePeriod BIGINT NOT NULL,"
|
||||||
+ " stream BIGINT NOT NULL,"
|
|
||||||
+ " contactId INT," // Null if contact is pending
|
+ " contactId INT," // Null if contact is pending
|
||||||
+ " pendingContactId _HASH," // Null if not pending
|
+ " pendingContactId _HASH," // Null if not pending
|
||||||
+ " PRIMARY KEY (transportId, staticKeySetId),"
|
+ " rootKey _SECRET NOT NULL,"
|
||||||
|
+ " alice BOOLEAN NOT NULL,"
|
||||||
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
|
+ " stream BIGINT NOT NULL,"
|
||||||
|
+ " PRIMARY KEY (transportId, keySetId),"
|
||||||
+ " FOREIGN KEY (transportId)"
|
+ " FOREIGN KEY (transportId)"
|
||||||
+ " REFERENCES transports (transportId)"
|
+ " REFERENCES transports (transportId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " UNIQUE (staticKeySetId),"
|
+ " UNIQUE (keySetId),"
|
||||||
+ " FOREIGN KEY (contactId)"
|
+ " FOREIGN KEY (contactId)"
|
||||||
+ " REFERENCES contacts (contactId)"
|
+ " REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " ON DELETE CASCADE,"
|
||||||
@@ -310,18 +318,19 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String CREATE_INCOMING_STATIC_KEYS =
|
private static final String CREATE_INCOMING_STATIC_KEYS =
|
||||||
"CREATE TABLE incomingStaticKeys"
|
"CREATE TABLE incomingStaticKeys"
|
||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " staticKeySetId INT NOT NULL,"
|
+ " keySetId INT NOT NULL,"
|
||||||
+ " timePeriod BIGINT NOT NULL,"
|
+ " timePeriod BIGINT NOT NULL,"
|
||||||
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
+ " base BIGINT NOT NULL,"
|
+ " base BIGINT NOT NULL,"
|
||||||
+ " bitmap _BINARY NOT NULL,"
|
+ " bitmap _BINARY NOT NULL,"
|
||||||
+ " periodOffset INT NOT NULL,"
|
+ " periodOffset INT NOT NULL,"
|
||||||
+ " PRIMARY KEY (transportId, staticKeySetId,"
|
+ " PRIMARY KEY (transportId, keySetId, periodOffset),"
|
||||||
+ " periodOffset),"
|
|
||||||
+ " FOREIGN KEY (transportId)"
|
+ " FOREIGN KEY (transportId)"
|
||||||
+ " REFERENCES transports (transportId)"
|
+ " REFERENCES transports (transportId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " FOREIGN KEY (staticKeySetId)"
|
+ " FOREIGN KEY (keySetId)"
|
||||||
+ " REFERENCES outgoingStaticKeys (staticKeySetId)"
|
+ " REFERENCES outgoingStaticKeys (keySetId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
|
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
|
||||||
@@ -938,6 +947,104 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StaticTransportKeySetId addStaticTransportKeys(Connection txn,
|
||||||
|
ContactId c, StaticTransportKeys k) throws DbException {
|
||||||
|
return addStaticTransportKeys(txn, c, null, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StaticTransportKeySetId addStaticTransportKeys(Connection txn,
|
||||||
|
PendingContactId p, StaticTransportKeys k) throws DbException {
|
||||||
|
return addStaticTransportKeys(txn, null, p, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StaticTransportKeySetId addStaticTransportKeys(Connection txn,
|
||||||
|
@Nullable ContactId c, @Nullable PendingContactId p,
|
||||||
|
StaticTransportKeys k) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
// Store the outgoing keys
|
||||||
|
String sql = "INSERT INTO outgoingStaticKeys (contactId,"
|
||||||
|
+ " pendingContactId, transportId, rootKey, alice,"
|
||||||
|
+ " timePeriod, tagKey, headerKey, stream)"
|
||||||
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
if (c == null) ps.setNull(1, INTEGER);
|
||||||
|
else ps.setInt(1, c.getInt());
|
||||||
|
if (p == null) ps.setNull(2, BINARY);
|
||||||
|
else ps.setBytes(2, p.getBytes());
|
||||||
|
ps.setString(3, k.getTransportId().getString());
|
||||||
|
ps.setBytes(4, k.getRootKey().getBytes());
|
||||||
|
ps.setBoolean(5, k.isAlice());
|
||||||
|
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
||||||
|
ps.setLong(6, outCurr.getTimePeriod());
|
||||||
|
ps.setBytes(7, outCurr.getTagKey().getBytes());
|
||||||
|
ps.setBytes(8, outCurr.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(9, outCurr.getStreamCounter());
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if (affected != 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
// Get the new (highest) key set ID
|
||||||
|
sql = "SELECT keySetId FROM outgoingStaticKeys"
|
||||||
|
+ " ORDER BY keySetId DESC LIMIT 1";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
if (!rs.next()) throw new DbStateException();
|
||||||
|
StaticTransportKeySetId keySetId = new
|
||||||
|
StaticTransportKeySetId(rs.getInt(1));
|
||||||
|
if (rs.next()) throw new DbStateException();
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
// Store the incoming keys
|
||||||
|
sql = "INSERT INTO incomingStaticKeys (keySetId, transportId,"
|
||||||
|
+ " timePeriod, tagKey, headerKey, base, bitmap,"
|
||||||
|
+ " periodOffset)"
|
||||||
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, keySetId.getInt());
|
||||||
|
ps.setString(2, k.getTransportId().getString());
|
||||||
|
// Previous time period
|
||||||
|
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
||||||
|
ps.setLong(3, inPrev.getTimePeriod());
|
||||||
|
ps.setBytes(4, inPrev.getTagKey().getBytes());
|
||||||
|
ps.setBytes(5, inPrev.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(6, inPrev.getWindowBase());
|
||||||
|
ps.setBytes(7, inPrev.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_PREV);
|
||||||
|
ps.addBatch();
|
||||||
|
// Current time period
|
||||||
|
IncomingKeys inCurr = k.getCurrentIncomingKeys();
|
||||||
|
ps.setLong(3, inCurr.getTimePeriod());
|
||||||
|
ps.setBytes(4, inCurr.getTagKey().getBytes());
|
||||||
|
ps.setBytes(5, inCurr.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(6, inCurr.getWindowBase());
|
||||||
|
ps.setBytes(7, inCurr.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_CURR);
|
||||||
|
ps.addBatch();
|
||||||
|
// Next time period
|
||||||
|
IncomingKeys inNext = k.getNextIncomingKeys();
|
||||||
|
ps.setLong(3, inNext.getTimePeriod());
|
||||||
|
ps.setBytes(4, inNext.getTagKey().getBytes());
|
||||||
|
ps.setBytes(5, inNext.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(6, inNext.getWindowBase());
|
||||||
|
ps.setBytes(7, inNext.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_NEXT);
|
||||||
|
ps.addBatch();
|
||||||
|
int[] batchAffected = ps.executeBatch();
|
||||||
|
if (batchAffected.length != 3) throw new DbStateException();
|
||||||
|
for (int rows : batchAffected)
|
||||||
|
if (rows != 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
return keySetId;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(rs, LOG, WARNING);
|
||||||
|
tryToClose(ps, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTransport(Connection txn, TransportId t, int maxLatency)
|
public void addTransport(Connection txn, TransportId t, int maxLatency)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -1149,6 +1256,29 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsPendingContact(Connection txn, PendingContactId p)
|
||||||
|
throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT NULL FROM pendingContacts"
|
||||||
|
+ " WHERE pendingContactId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setBytes(1, p.getBytes());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
boolean found = rs.next();
|
||||||
|
if (rs.next()) throw new DbStateException();
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return found;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(rs, LOG, WARNING);
|
||||||
|
tryToClose(ps, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsTransport(Connection txn, TransportId t)
|
public boolean containsTransport(Connection txn, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -2190,6 +2320,87 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<StaticTransportKeySet> getStaticTransportKeys(
|
||||||
|
Connection txn, TransportId t) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
// Retrieve the incoming keys
|
||||||
|
String sql = "SELECT timePeriod, tagKey, headerKey, base, bitmap"
|
||||||
|
+ " FROM incomingStaticKeys"
|
||||||
|
+ " WHERE transportId = ?"
|
||||||
|
+ " ORDER BY keySetId, periodOffset";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setString(1, t.getString());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
List<IncomingKeys> inKeys = new ArrayList<>();
|
||||||
|
while (rs.next()) {
|
||||||
|
long timePeriod = rs.getLong(1);
|
||||||
|
SecretKey tagKey = new SecretKey(rs.getBytes(2));
|
||||||
|
SecretKey headerKey = new SecretKey(rs.getBytes(3));
|
||||||
|
long windowBase = rs.getLong(4);
|
||||||
|
byte[] windowBitmap = rs.getBytes(5);
|
||||||
|
inKeys.add(new IncomingKeys(tagKey, headerKey, timePeriod,
|
||||||
|
windowBase, windowBitmap));
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
// Retrieve the outgoing keys in the same order
|
||||||
|
sql = "SELECT keySetId, contactId, pendingContactId, timePeriod,"
|
||||||
|
+ " tagKey, headerKey, rootKey, alice, stream"
|
||||||
|
+ " FROM outgoingStaticKeys"
|
||||||
|
+ " WHERE transportId = ?"
|
||||||
|
+ " ORDER BY keySetId";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setString(1, t.getString());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
Collection<StaticTransportKeySet> keys = new ArrayList<>();
|
||||||
|
for (int i = 0; rs.next(); i++) {
|
||||||
|
// There should be three times as many incoming keys
|
||||||
|
if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
|
||||||
|
StaticTransportKeySetId keySetId =
|
||||||
|
new StaticTransportKeySetId(rs.getInt(1));
|
||||||
|
ContactId contactId = null;
|
||||||
|
int cId = rs.getInt(2);
|
||||||
|
if (!rs.wasNull()) contactId = new ContactId(cId);
|
||||||
|
PendingContactId pendingContactId = null;
|
||||||
|
byte[] pId = rs.getBytes(3);
|
||||||
|
if (!rs.wasNull()) pendingContactId = new PendingContactId(pId);
|
||||||
|
long timePeriod = rs.getLong(4);
|
||||||
|
SecretKey tagKey = new SecretKey(rs.getBytes(5));
|
||||||
|
SecretKey headerKey = new SecretKey(rs.getBytes(6));
|
||||||
|
SecretKey rootKey = new SecretKey(rs.getBytes(7));
|
||||||
|
boolean alice = rs.getBoolean(8);
|
||||||
|
long streamCounter = rs.getLong(9);
|
||||||
|
OutgoingKeys outCurr = new OutgoingKeys(tagKey, headerKey,
|
||||||
|
timePeriod, streamCounter, true);
|
||||||
|
IncomingKeys inPrev = inKeys.get(i * 3);
|
||||||
|
IncomingKeys inCurr = inKeys.get(i * 3 + 1);
|
||||||
|
IncomingKeys inNext = inKeys.get(i * 3 + 2);
|
||||||
|
StaticTransportKeys staticTransportKeys =
|
||||||
|
new StaticTransportKeys(t, inPrev, inCurr, inNext,
|
||||||
|
outCurr, rootKey, alice);
|
||||||
|
if (contactId == null) {
|
||||||
|
if (pendingContactId == null) throw new DbStateException();
|
||||||
|
keys.add(new StaticTransportKeySet(keySetId,
|
||||||
|
pendingContactId, staticTransportKeys));
|
||||||
|
} else {
|
||||||
|
if (pendingContactId != null) throw new DbStateException();
|
||||||
|
keys.add(new StaticTransportKeySet(keySetId, contactId,
|
||||||
|
staticTransportKeys));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return keys;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(rs, LOG, WARNING);
|
||||||
|
tryToClose(ps, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TransportKeySet> getTransportKeys(Connection txn,
|
public Collection<TransportKeySet> getTransportKeys(Connection txn,
|
||||||
TransportId t) throws DbException {
|
TransportId t) throws DbException {
|
||||||
@@ -2257,6 +2468,25 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementStreamCounter(Connection txn, TransportId t,
|
||||||
|
StaticTransportKeySetId k) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
String sql = "UPDATE outgoingStaticKeys SET stream = stream + 1"
|
||||||
|
+ " WHERE transportId = ? AND keySetId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setString(1, t.getString());
|
||||||
|
ps.setInt(2, k.getInt());
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if (affected != 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(ps, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incrementStreamCounter(Connection txn, TransportId t,
|
public void incrementStreamCounter(Connection txn, TransportId t,
|
||||||
TransportKeySetId k) throws DbException {
|
TransportKeySetId k) throws DbException {
|
||||||
@@ -2339,8 +2569,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
g.getBytes(), meta, "groupMetadata", "groupId");
|
g.getBytes(), meta, "groupMetadata", "groupId");
|
||||||
if (added.isEmpty()) return;
|
if (added.isEmpty()) return;
|
||||||
// Insert any keys that don't already exist
|
// Insert any keys that don't already exist
|
||||||
String sql = "INSERT INTO groupMetadata (groupId, metaKey, value)"
|
String sql =
|
||||||
+ " VALUES (?, ?, ?)";
|
"INSERT INTO groupMetadata (groupId, metaKey, value)"
|
||||||
|
+ " VALUES (?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
for (Entry<String, byte[]> e : added.entrySet()) {
|
for (Entry<String, byte[]> e : added.entrySet()) {
|
||||||
@@ -2488,7 +2719,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
int[] batchAffected = ps.executeBatch();
|
int[] batchAffected = ps.executeBatch();
|
||||||
if (batchAffected.length != s.size()) throw new DbStateException();
|
if (batchAffected.length != s.size())
|
||||||
|
throw new DbStateException();
|
||||||
for (int rows : batchAffected) {
|
for (int rows : batchAffected) {
|
||||||
if (rows < 0) throw new DbStateException();
|
if (rows < 0) throw new DbStateException();
|
||||||
if (rows > 1) throw new DbStateException();
|
if (rows > 1) throw new DbStateException();
|
||||||
@@ -2509,7 +2741,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
updateIndex++;
|
updateIndex++;
|
||||||
}
|
}
|
||||||
batchAffected = ps.executeBatch();
|
batchAffected = ps.executeBatch();
|
||||||
if (batchAffected.length != inserted) throw new DbStateException();
|
if (batchAffected.length != inserted)
|
||||||
|
throw new DbStateException();
|
||||||
for (int rows : batchAffected)
|
for (int rows : batchAffected)
|
||||||
if (rows != 1) throw new DbStateException();
|
if (rows != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -2610,7 +2843,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeGroupVisibility(Connection txn, ContactId c, GroupId g)
|
public void removeGroupVisibility(Connection txn, ContactId c, GroupId
|
||||||
|
g)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
@@ -2655,7 +2889,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
public void removeMessage(Connection txn, MessageId m) throws
|
||||||
|
DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "DELETE FROM messages WHERE messageId = ?";
|
String sql = "DELETE FROM messages WHERE messageId = ?";
|
||||||
@@ -2714,6 +2949,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeStaticTransportKeys(Connection txn, TransportId t,
|
||||||
|
StaticTransportKeySetId 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 outgoingStaticKeys"
|
||||||
|
+ " 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, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTransport(Connection txn, TransportId t)
|
public void removeTransport(Connection txn, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -2776,7 +3032,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "UPDATE contacts SET verified = ? WHERE contactId = ?";
|
String sql =
|
||||||
|
"UPDATE contacts SET verified = ? WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBoolean(1, true);
|
ps.setBoolean(1, true);
|
||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
@@ -2794,7 +3051,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "UPDATE contacts SET active = ? WHERE contactId = ?";
|
String sql =
|
||||||
|
"UPDATE contacts SET active = ? WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBoolean(1, active);
|
ps.setBoolean(1, active);
|
||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
@@ -2812,7 +3070,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
@Nullable String alias) throws DbException {
|
@Nullable String alias) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "UPDATE contacts SET alias = ? WHERE contactId = ?";
|
String sql =
|
||||||
|
"UPDATE contacts SET alias = ? WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
if (alias == null) ps.setNull(1, VARCHAR);
|
if (alias == null) ps.setNull(1, VARCHAR);
|
||||||
else ps.setString(1, alias);
|
else ps.setString(1, alias);
|
||||||
@@ -2883,11 +3142,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessageState(Connection txn, MessageId m, MessageState state)
|
public void setMessageState(Connection txn, MessageId m, MessageState
|
||||||
|
state)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "UPDATE messages SET state = ? WHERE messageId = ?";
|
String sql =
|
||||||
|
"UPDATE messages SET state = ? WHERE messageId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, state.getValue());
|
ps.setInt(1, state.getValue());
|
||||||
ps.setBytes(2, m.getBytes());
|
ps.setBytes(2, m.getBytes());
|
||||||
@@ -2895,7 +3156,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
// Update denormalised column in messageMetadata
|
// Update denormalised column in messageMetadata
|
||||||
sql = "UPDATE messageMetadata SET state = ? WHERE messageId = ?";
|
sql =
|
||||||
|
"UPDATE messageMetadata SET state = ? WHERE messageId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, state.getValue());
|
ps.setInt(1, state.getValue());
|
||||||
ps.setBytes(2, m.getBytes());
|
ps.setBytes(2, m.getBytes());
|
||||||
@@ -2922,7 +3184,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
// Update denormalised column in messageDependencies if dependency
|
// Update denormalised column in messageDependencies if dependency
|
||||||
// is present and in same group as dependent
|
// is present and in same group as dependent
|
||||||
sql = "UPDATE messageDependencies SET dependencyState = ?"
|
sql = "UPDATE messageDependencies SET dependencyState = ?"
|
||||||
+ " WHERE dependencyId = ? AND dependencyState IS NOT NULL";
|
+
|
||||||
|
" WHERE dependencyId = ? AND dependencyState IS NOT NULL";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, state.getValue());
|
ps.setInt(1, state.getValue());
|
||||||
ps.setBytes(2, m.getBytes());
|
ps.setBytes(2, m.getBytes());
|
||||||
@@ -2979,7 +3242,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m,
|
public void updateExpiryTimeAndEta(Connection txn, ContactId
|
||||||
|
c, MessageId m,
|
||||||
int maxLatency) throws DbException {
|
int maxLatency) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@@ -3081,4 +3345,71 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStaticTransportKeys(Connection txn,
|
||||||
|
StaticTransportKeySet ks) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
// Update the outgoing keys
|
||||||
|
String sql = "UPDATE outgoingStaticKeys SET timePeriod = ?,"
|
||||||
|
+ " tagKey = ?, headerKey = ?, stream = ?"
|
||||||
|
+ " WHERE transportId = ? AND keySetId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
StaticTransportKeys k = ks.getKeys();
|
||||||
|
OutgoingKeys outCurr = k.getCurrentOutgoingKeys();
|
||||||
|
ps.setLong(1, outCurr.getTimePeriod());
|
||||||
|
ps.setBytes(2, outCurr.getTagKey().getBytes());
|
||||||
|
ps.setBytes(3, outCurr.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(4, outCurr.getStreamCounter());
|
||||||
|
ps.setString(5, k.getTransportId().getString());
|
||||||
|
ps.setInt(6, ks.getKeySetId().getInt());
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
// Update the incoming keys
|
||||||
|
sql = "UPDATE incomingStaticKeys SET timePeriod = ?,"
|
||||||
|
+ " tagKey = ?, headerKey = ?, base = ?, bitmap = ?"
|
||||||
|
+ " WHERE transportId = ? AND keySetId = ?"
|
||||||
|
+ " AND periodOffset = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setString(6, k.getTransportId().getString());
|
||||||
|
ps.setInt(7, ks.getKeySetId().getInt());
|
||||||
|
// Previous time period
|
||||||
|
IncomingKeys inPrev = k.getPreviousIncomingKeys();
|
||||||
|
ps.setLong(1, inPrev.getTimePeriod());
|
||||||
|
ps.setBytes(2, inPrev.getTagKey().getBytes());
|
||||||
|
ps.setBytes(3, inPrev.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(4, inPrev.getWindowBase());
|
||||||
|
ps.setBytes(5, inPrev.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_PREV);
|
||||||
|
ps.addBatch();
|
||||||
|
// Current time period
|
||||||
|
IncomingKeys inCurr = k.getCurrentIncomingKeys();
|
||||||
|
ps.setLong(1, inCurr.getTimePeriod());
|
||||||
|
ps.setBytes(2, inCurr.getTagKey().getBytes());
|
||||||
|
ps.setBytes(3, inCurr.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(4, inCurr.getWindowBase());
|
||||||
|
ps.setBytes(5, inCurr.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_CURR);
|
||||||
|
ps.addBatch();
|
||||||
|
// Next time period
|
||||||
|
IncomingKeys inNext = k.getNextIncomingKeys();
|
||||||
|
ps.setLong(1, inNext.getTimePeriod());
|
||||||
|
ps.setBytes(2, inNext.getTagKey().getBytes());
|
||||||
|
ps.setBytes(3, inNext.getHeaderKey().getBytes());
|
||||||
|
ps.setLong(4, inNext.getWindowBase());
|
||||||
|
ps.setBytes(5, inNext.getWindowBitmap());
|
||||||
|
ps.setInt(8, OFFSET_NEXT);
|
||||||
|
ps.addBatch();
|
||||||
|
int[] batchAffected = ps.executeBatch();
|
||||||
|
if (batchAffected.length != 3) throw new DbStateException();
|
||||||
|
for (int rows : batchAffected)
|
||||||
|
if (rows < 0 || rows > 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(ps, LOG, WARNING);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,42 +45,46 @@ class Migration41_42 implements Migration<Connection> {
|
|||||||
s.execute("ALTER TABLE incomingKeys"
|
s.execute("ALTER TABLE incomingKeys"
|
||||||
+ " DROP COLUMN contactId");
|
+ " DROP COLUMN contactId");
|
||||||
s.execute(dbTypes.replaceTypes("CREATE TABLE pendingContacts"
|
s.execute(dbTypes.replaceTypes("CREATE TABLE pendingContacts"
|
||||||
+ " (pendingContactId _HASH NOT NULL,"
|
+ " (pendingContactId _HASH NOT NULL,"
|
||||||
+ " PRIMARY KEY (pendingContactId))"));
|
+ " PRIMARY KEY (pendingContactId))"));
|
||||||
s.execute(dbTypes.replaceTypes("CREATE TABLE outgoingStaticKeys"
|
s.execute(dbTypes.replaceTypes("CREATE TABLE outgoingStaticKeys"
|
||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " staticKeySetId _COUNTER,"
|
+ " keySetId _COUNTER,"
|
||||||
+ " rootKey _SECRET NOT NULL,"
|
+ " timePeriod BIGINT NOT NULL,"
|
||||||
+ " timePeriod BIGINT NOT NULL,"
|
+ " contactId INT," // Null if contact is pending
|
||||||
+ " stream BIGINT NOT NULL,"
|
+ " pendingContactId _HASH," // Null if not pending
|
||||||
+ " contactId INT," // Null if contact is pending
|
+ " rootKey _SECRET NOT NULL,"
|
||||||
+ " pendingContactId _HASH," // Null if not pending
|
+ " alice BOOLEAN NOT NULL,"
|
||||||
+ " PRIMARY KEY (transportId, staticKeySetId),"
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
+ " FOREIGN KEY (transportId)"
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
+ " REFERENCES transports (transportId)"
|
+ " stream BIGINT NOT NULL,"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " PRIMARY KEY (transportId, keySetId),"
|
||||||
+ " UNIQUE (staticKeySetId),"
|
+ " FOREIGN KEY (transportId)"
|
||||||
+ " FOREIGN KEY (contactId)"
|
+ " REFERENCES transports (transportId)"
|
||||||
+ " REFERENCES contacts (contactId)"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " UNIQUE (keySetId),"
|
||||||
+ " FOREIGN KEY (pendingContactId)"
|
+ " FOREIGN KEY (contactId)"
|
||||||
+ " REFERENCES pendingContacts (pendingContactId)"
|
+ " REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)"));
|
+ " ON DELETE CASCADE,"
|
||||||
|
+ " FOREIGN KEY (pendingContactId)"
|
||||||
|
+ " REFERENCES pendingContacts (pendingContactId)"
|
||||||
|
+ " ON DELETE CASCADE)"));
|
||||||
s.execute(dbTypes.replaceTypes("CREATE TABLE incomingStaticKeys"
|
s.execute(dbTypes.replaceTypes("CREATE TABLE incomingStaticKeys"
|
||||||
+ " (transportId _STRING NOT NULL,"
|
+ " (transportId _STRING NOT NULL,"
|
||||||
+ " staticKeySetId INT NOT NULL,"
|
+ " keySetId INT NOT NULL,"
|
||||||
+ " timePeriod BIGINT NOT NULL,"
|
+ " timePeriod BIGINT NOT NULL,"
|
||||||
+ " base BIGINT NOT NULL,"
|
+ " tagKey _SECRET NOT NULL,"
|
||||||
+ " bitmap _BINARY NOT NULL,"
|
+ " headerKey _SECRET NOT NULL,"
|
||||||
+ " periodOffset INT NOT NULL,"
|
+ " base BIGINT NOT NULL,"
|
||||||
+ " PRIMARY KEY (transportId, staticKeySetId,"
|
+ " bitmap _BINARY NOT NULL,"
|
||||||
+ " periodOffset),"
|
+ " periodOffset INT NOT NULL,"
|
||||||
+ " FOREIGN KEY (transportId)"
|
+ " PRIMARY KEY (transportId, keySetId, periodOffset),"
|
||||||
+ " REFERENCES transports (transportId)"
|
+ " FOREIGN KEY (transportId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " REFERENCES transports (transportId)"
|
||||||
+ " FOREIGN KEY (staticKeySetId)"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " REFERENCES outgoingStaticKeys (staticKeySetId)"
|
+ " FOREIGN KEY (keySetId)"
|
||||||
+ " ON DELETE CASCADE)"));
|
+ " REFERENCES outgoingStaticKeys (keySetId)"
|
||||||
|
+ " ON DELETE CASCADE)"));
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s, LOG, WARNING);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user