mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Renamed ContactTransport -> Endpoint, added more database exceptions.
This commit is contained in:
@@ -3,7 +3,7 @@ package net.sf.briar.api.crypto;
|
|||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.transport.ConnectionContext;
|
import net.sf.briar.api.transport.ConnectionContext;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
|
|
||||||
public interface KeyManager {
|
public interface KeyManager {
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ public interface KeyManager {
|
|||||||
ConnectionContext getConnectionContext(ContactId c, TransportId t);
|
ConnectionContext getConnectionContext(ContactId c, TransportId t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever a contact transport has been added. The initial secret
|
* Called whenever an endpoint has been added. The initial secret
|
||||||
* is erased before returning.
|
* is erased before returning.
|
||||||
*/
|
*/
|
||||||
void contactTransportAdded(ContactTransport ct, byte[] initialSecret);
|
void endpointAdded(Endpoint ep, byte[] initialSecret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import net.sf.briar.api.protocol.SubscriptionUpdate;
|
|||||||
import net.sf.briar.api.protocol.TransportAck;
|
import net.sf.briar.api.protocol.TransportAck;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,8 +54,8 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
ContactId addContact() throws DbException;
|
ContactId addContact() throws DbException;
|
||||||
|
|
||||||
/** Adds a contact transport to the database. */
|
/** Adds an endpoitn to the database. */
|
||||||
void addContactTransport(ContactTransport ct) throws DbException;
|
void addEndpoint(Endpoint ep) throws DbException;
|
||||||
|
|
||||||
/** Adds a locally generated group message to the database. */
|
/** Adds a locally generated group message to the database. */
|
||||||
void addLocalGroupMessage(Message m) throws DbException;
|
void addLocalGroupMessage(Message m) throws DbException;
|
||||||
@@ -239,8 +239,8 @@ public interface DatabaseComponent {
|
|||||||
void removeContact(ContactId c) throws DbException;
|
void removeContact(ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the connection reordering window for the given contact transport
|
* Sets the connection reordering window for the given endoint in the given
|
||||||
* in the given rotation period.
|
* rotation period.
|
||||||
*/
|
*/
|
||||||
void setConnectionWindow(ContactId c, TransportId t, long period,
|
void setConnectionWindow(ContactId c, TransportId t, long period,
|
||||||
long centre, byte[] bitmap) throws DbException;
|
long centre, byte[] bitmap) throws DbException;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ package net.sf.briar.api.db;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when a database operation is attempted for a contact that is not in
|
* Thrown when a database operation is attempted for a contact that is not in
|
||||||
* the database.
|
* the database. This exception may occur due to concurrent updates and does
|
||||||
|
* not indicate a database error.
|
||||||
*/
|
*/
|
||||||
public class NoSuchContactException extends DbException {
|
public class NoSuchContactException extends DbException {
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.sf.briar.api.db;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when a database operation is attempted for a contact transport that
|
|
||||||
* is not in the database.
|
|
||||||
*/
|
|
||||||
public class NoSuchContactTransportException extends DbException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -6274982612759573100L;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a database operation is attempted for a group to which the user
|
||||||
|
* does not subscribe. This exception may occur due to concurrent updates and
|
||||||
|
* does not indicate a database error.
|
||||||
|
*/
|
||||||
|
public class NoSuchSubscriptionException extends DbException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5494178507342571697L;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a database operation is attempted for a transport that is not in
|
||||||
|
* the database. This exception may occur due to concurrent updates and does
|
||||||
|
* not indicate a database error.
|
||||||
|
*/
|
||||||
|
public class NoSuchTransportException extends DbException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6274982612759573100L;
|
||||||
|
}
|
||||||
@@ -3,14 +3,14 @@ package net.sf.briar.api.transport;
|
|||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
|
|
||||||
public class ContactTransport {
|
public class Endpoint {
|
||||||
|
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
private final long epoch, clockDiff, latency;
|
private final long epoch, clockDiff, latency;
|
||||||
private final boolean alice;
|
private final boolean alice;
|
||||||
|
|
||||||
public ContactTransport(ContactId contactId, TransportId transportId,
|
public Endpoint(ContactId contactId, TransportId transportId,
|
||||||
long epoch, long clockDiff, long latency, boolean alice) {
|
long epoch, long clockDiff, long latency, boolean alice) {
|
||||||
this.contactId = contactId;
|
this.contactId = contactId;
|
||||||
this.transportId = transportId;
|
this.transportId = transportId;
|
||||||
@@ -4,7 +4,7 @@ import static net.sf.briar.api.transport.TransportConstants.CONNECTION_WINDOW_SI
|
|||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
|
|
||||||
public class TemporarySecret extends ContactTransport {
|
public class TemporarySecret extends Endpoint {
|
||||||
|
|
||||||
private final long period, outgoing, centre;
|
private final long period, outgoing, centre;
|
||||||
private final byte[] secret, bitmap;
|
private final byte[] secret, bitmap;
|
||||||
@@ -30,10 +30,10 @@ public class TemporarySecret extends ContactTransport {
|
|||||||
secret, 0L, 0L, new byte[CONNECTION_WINDOW_SIZE / 8]);
|
secret, 0L, 0L, new byte[CONNECTION_WINDOW_SIZE / 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a temporary secret derived from the given contact transport. */
|
/** Creates a temporary secret derived from the given endpoint. */
|
||||||
public TemporarySecret(ContactTransport ct, long period, byte[] secret) {
|
public TemporarySecret(Endpoint ep, long period, byte[] secret) {
|
||||||
this(ct.getContactId(), ct.getTransportId(), ct.getEpoch(),
|
this(ep.getContactId(), ep.getTransportId(), ep.getEpoch(),
|
||||||
ct.getClockDifference(), ct.getLatency(), ct.getAlice(),
|
ep.getClockDifference(), ep.getLatency(), ep.getAlice(),
|
||||||
period, secret);
|
period, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import net.sf.briar.api.protocol.SubscriptionUpdate;
|
|||||||
import net.sf.briar.api.protocol.TransportAck;
|
import net.sf.briar.api.protocol.TransportAck;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,11 +82,11 @@ interface Database<T> {
|
|||||||
ContactId addContact(T txn) throws DbException;
|
ContactId addContact(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a contact transport to the database.
|
* Adds an endpoint to the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, transport read, window write.
|
* Locking: contact read, transport read, window write.
|
||||||
*/
|
*/
|
||||||
void addContactTransport(T txn, ContactTransport ct) throws DbException;
|
void addEndpoint(T txn, Endpoint ep) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given message, or returns false if the message is already in
|
* Stores the given message, or returns false if the message is already in
|
||||||
@@ -156,14 +156,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
boolean containsContact(T txn, ContactId c) throws DbException;
|
boolean containsContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the database contains the given contact transport.
|
|
||||||
* <p>
|
|
||||||
* Locking: contact read, transport read, window read.
|
|
||||||
*/
|
|
||||||
boolean containsContactTransport(T txn, ContactId c, TransportId t)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given message.
|
* Returns true if the database contains the given message.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -178,6 +170,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
boolean containsSubscription(T txn, GroupId g) throws DbException;
|
boolean containsSubscription(T txn, GroupId g) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the database contains the given transport.
|
||||||
|
* <p>
|
||||||
|
* Locking: contact read, transport read.
|
||||||
|
*/
|
||||||
|
boolean containsTransport(T txn, TransportId t) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the user subscribes to the given group and the
|
* Returns true if the user subscribes to the given group and the
|
||||||
* subscription is visible to the given contact.
|
* subscription is visible to the given contact.
|
||||||
@@ -202,11 +201,11 @@ interface Database<T> {
|
|||||||
Collection<ContactId> getContacts(T txn) throws DbException;
|
Collection<ContactId> getContacts(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all contact transports.
|
* Returns all endpoints.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, transport read, window read.
|
* Locking: contact read, transport read, window read.
|
||||||
*/
|
*/
|
||||||
Collection<ContactTransport> getContactTransports(T txn) throws DbException;
|
Collection<Endpoint> getEndpoints(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the amount of free storage space available to the database, in
|
* Returns the amount of free storage space available to the database, in
|
||||||
@@ -541,8 +540,8 @@ interface Database<T> {
|
|||||||
void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
|
void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the connection reordering window for the given contact transport in
|
* Sets the connection reordering window for the given endpoint in the
|
||||||
* the given rotation period.
|
* given rotation period.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, transport read, window write.
|
* Locking: contact read, transport read, window write.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ import net.sf.briar.api.db.DatabaseComponent;
|
|||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.MessageHeader;
|
import net.sf.briar.api.db.MessageHeader;
|
||||||
import net.sf.briar.api.db.NoSuchContactException;
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.NoSuchContactTransportException;
|
import net.sf.briar.api.db.NoSuchSubscriptionException;
|
||||||
|
import net.sf.briar.api.db.NoSuchTransportException;
|
||||||
import net.sf.briar.api.db.event.ContactAddedEvent;
|
import net.sf.briar.api.db.event.ContactAddedEvent;
|
||||||
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||||
@@ -61,7 +62,7 @@ import net.sf.briar.api.protocol.SubscriptionUpdate;
|
|||||||
import net.sf.briar.api.protocol.TransportAck;
|
import net.sf.briar.api.protocol.TransportAck;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -196,7 +197,7 @@ DatabaseCleaner.Callback {
|
|||||||
for(DatabaseListener d : listeners) d.eventOccurred(e);
|
for(DatabaseListener d : listeners) d.eventOccurred(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addContactTransport(ContactTransport ct) throws DbException {
|
public void addEndpoint(Endpoint ep) throws DbException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
transportLock.readLock().lock();
|
transportLock.readLock().lock();
|
||||||
@@ -205,9 +206,11 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
if(!db.containsContact(txn, ct.getContactId()))
|
if(!db.containsContact(txn, ep.getContactId()))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
db.addContactTransport(txn, ct);
|
if(!db.containsTransport(txn, ep.getTransportId()))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
|
db.addEndpoint(txn, ep);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
@@ -381,9 +384,10 @@ DatabaseCleaner.Callback {
|
|||||||
new ArrayList<TemporarySecret>();
|
new ArrayList<TemporarySecret>();
|
||||||
for(TemporarySecret s : secrets) {
|
for(TemporarySecret s : secrets) {
|
||||||
ContactId c = s.getContactId();
|
ContactId c = s.getContactId();
|
||||||
|
if(!db.containsContact(txn, c)) continue;
|
||||||
TransportId t = s.getTransportId();
|
TransportId t = s.getTransportId();
|
||||||
if(db.containsContactTransport(txn, c, t))
|
if(!db.containsTransport(txn, t)) continue;
|
||||||
relevant.add(s);
|
relevant.add(s);
|
||||||
}
|
}
|
||||||
if(!secrets.isEmpty()) db.addSecrets(txn, relevant);
|
if(!secrets.isEmpty()) db.addSecrets(txn, relevant);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -725,6 +729,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsContact(txn, c))
|
||||||
|
throw new NoSuchContactException();
|
||||||
Collection<TransportAck> acks = db.getTransportAcks(txn, c);
|
Collection<TransportAck> acks = db.getTransportAcks(txn, c);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
return acks;
|
return acks;
|
||||||
@@ -748,6 +754,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsContact(txn, c))
|
||||||
|
throw new NoSuchContactException();
|
||||||
Collection<TransportUpdate> updates =
|
Collection<TransportUpdate> updates =
|
||||||
db.getTransportUpdates(txn, c);
|
db.getTransportUpdates(txn, c);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -769,6 +777,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
TransportConfig config = db.getConfig(txn, t);
|
TransportConfig config = db.getConfig(txn, t);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
return config;
|
return config;
|
||||||
@@ -804,6 +814,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
TransportProperties properties = db.getLocalProperties(txn, t);
|
TransportProperties properties = db.getLocalProperties(txn, t);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
return properties;
|
return properties;
|
||||||
@@ -822,6 +834,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsSubscription(txn, g))
|
||||||
|
throw new NoSuchSubscriptionException();
|
||||||
Collection<MessageHeader> headers =
|
Collection<MessageHeader> headers =
|
||||||
db.getMessageHeaders(txn, g);
|
db.getMessageHeaders(txn, g);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -951,6 +965,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsSubscription(txn, g))
|
||||||
|
throw new NoSuchSubscriptionException();
|
||||||
Collection<ContactId> visible = db.getVisibility(txn, g);
|
Collection<ContactId> visible = db.getVisibility(txn, g);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
return visible;
|
return visible;
|
||||||
@@ -1005,8 +1021,10 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
if(!db.containsContactTransport(txn, c, t))
|
if(!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactTransportException();
|
throw new NoSuchContactException();
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
long counter = db.incrementConnectionCounter(txn, c, t,
|
long counter = db.incrementConnectionCounter(txn, c, t,
|
||||||
period);
|
period);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -1032,6 +1050,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
db.mergeConfig(txn, t, c);
|
db.mergeConfig(txn, t, c);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
@@ -1050,6 +1070,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
if(!p.equals(db.getLocalProperties(txn, t))) {
|
if(!p.equals(db.getLocalProperties(txn, t))) {
|
||||||
db.mergeLocalProperties(txn, t, p);
|
db.mergeLocalProperties(txn, t, p);
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -1285,6 +1307,8 @@ DatabaseCleaner.Callback {
|
|||||||
if(!db.containsContact(txn, c))
|
if(!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
TransportId t = a.getId();
|
TransportId t = a.getId();
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
db.setTransportUpdateAcked(txn, c, t, a.getVersionNumber());
|
db.setTransportUpdateAcked(txn, c, t, a.getVersionNumber());
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
@@ -1368,6 +1392,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
db.removeTransport(txn, t);
|
db.removeTransport(txn, t);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
@@ -1390,8 +1416,10 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
if(!db.containsContactTransport(txn, c, t))
|
if(!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactTransportException();
|
throw new NoSuchContactException();
|
||||||
|
if(!db.containsTransport(txn, t))
|
||||||
|
throw new NoSuchTransportException();
|
||||||
db.setConnectionWindow(txn, c, t, period, centre,
|
db.setConnectionWindow(txn, c, t, period, centre,
|
||||||
bitmap);
|
bitmap);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -1504,6 +1532,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
|
if(!db.containsSubscription(txn, g))
|
||||||
|
throw new NoSuchSubscriptionException();
|
||||||
// Use HashSets for O(1) lookups, O(n) overall running time
|
// Use HashSets for O(1) lookups, O(n) overall running time
|
||||||
HashSet<ContactId> newVisible =
|
HashSet<ContactId> newVisible =
|
||||||
new HashSet<ContactId>(visible);
|
new HashSet<ContactId>(visible);
|
||||||
@@ -1554,7 +1584,7 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void unsubscribe(GroupId g) throws DbException {
|
public void unsubscribe(GroupId g) throws DbException {
|
||||||
Collection<ContactId> affected = null;
|
Collection<ContactId> affected;
|
||||||
contactLock.writeLock().lock();
|
contactLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
@@ -1563,10 +1593,10 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
if(db.containsSubscription(txn, g)) {
|
if(!db.containsSubscription(txn, g))
|
||||||
affected = db.getVisibility(txn, g);
|
throw new NoSuchSubscriptionException();
|
||||||
db.removeSubscription(txn, g);
|
affected = db.getVisibility(txn, g);
|
||||||
}
|
db.removeSubscription(txn, g);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
|
|||||||
@@ -31,18 +31,18 @@ import net.sf.briar.api.db.DbClosedException;
|
|||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.MessageHeader;
|
import net.sf.briar.api.db.MessageHeader;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
import net.sf.briar.api.protocol.RetentionAck;
|
|
||||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
|
||||||
import net.sf.briar.api.protocol.Group;
|
import net.sf.briar.api.protocol.Group;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
import net.sf.briar.api.protocol.Message;
|
import net.sf.briar.api.protocol.Message;
|
||||||
import net.sf.briar.api.protocol.MessageId;
|
import net.sf.briar.api.protocol.MessageId;
|
||||||
|
import net.sf.briar.api.protocol.RetentionAck;
|
||||||
|
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||||
import net.sf.briar.api.protocol.SubscriptionAck;
|
import net.sf.briar.api.protocol.SubscriptionAck;
|
||||||
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
||||||
import net.sf.briar.api.protocol.TransportAck;
|
import net.sf.briar.api.protocol.TransportAck;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
import net.sf.briar.util.FileUtils;
|
import net.sf.briar.util.FileUtils;
|
||||||
|
|
||||||
@@ -268,8 +268,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
// Locking: contact read, transport read, window
|
// Locking: contact read, transport read, window
|
||||||
private static final String CREATE_CONTACT_TRANSPORTS =
|
private static final String CREATE_ENDPOINTS =
|
||||||
"CREATE TABLE contactTransports"
|
"CREATE TABLE endpoints"
|
||||||
+ " (contactId INT NOT NULL,"
|
+ " (contactId INT NOT NULL,"
|
||||||
+ " transportId HASH NOT NULL,"
|
+ " transportId HASH NOT NULL,"
|
||||||
+ " epoch BIGINT NOT NULL,"
|
+ " epoch BIGINT NOT NULL,"
|
||||||
@@ -377,7 +377,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_VERSIONS));
|
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_VERSIONS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_PROPS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_PROPS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_VERSIONS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORT_VERSIONS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORTS));
|
s.executeUpdate(insertTypeNames(CREATE_ENDPOINTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_SECRETS));
|
s.executeUpdate(insertTypeNames(CREATE_SECRETS));
|
||||||
s.close();
|
s.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
@@ -567,20 +567,19 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addContactTransport(Connection txn, ContactTransport ct)
|
public void addEndpoint(Connection txn, Endpoint ep) throws DbException {
|
||||||
throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
String sql = "INSERT INTO contactTransports (contactId,"
|
String sql = "INSERT INTO endpoints (contactId, transportId,"
|
||||||
+ " transportId, epoch, clockDiff, latency, alice)"
|
+ " epoch, clockDiff, latency, alice)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, ct.getContactId().getInt());
|
ps.setInt(1, ep.getContactId().getInt());
|
||||||
ps.setBytes(2, ct.getTransportId().getBytes());
|
ps.setBytes(2, ep.getTransportId().getBytes());
|
||||||
ps.setLong(3, ct.getEpoch());
|
ps.setLong(3, ep.getEpoch());
|
||||||
ps.setLong(4, ct.getClockDifference());
|
ps.setLong(4, ep.getClockDifference());
|
||||||
ps.setLong(5, ct.getLatency());
|
ps.setLong(5, ep.getLatency());
|
||||||
ps.setBoolean(6, ct.getAlice());
|
ps.setBoolean(6, ep.getAlice());
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
if(affected != 1) throw new DbStateException();
|
if(affected != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -873,29 +872,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsContactTransport(Connection txn, ContactId c,
|
|
||||||
TransportId t) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
String sql = "SELECT NULL FROM contactTransports"
|
|
||||||
+ " WHERE contactId = ? AND transportId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setInt(1, c.getInt());
|
|
||||||
ps.setBytes(2, t.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);
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsMessage(Connection txn, MessageId m)
|
public boolean containsMessage(Connection txn, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -938,6 +914,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsTransport(Connection txn, TransportId t)
|
||||||
|
throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT NULL FROM transports WHERE transportId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setBytes(1, t.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);
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean containsVisibleSubscription(Connection txn, ContactId c,
|
public boolean containsVisibleSubscription(Connection txn, ContactId c,
|
||||||
GroupId g) throws DbException {
|
GroupId g) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1005,17 +1002,17 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ContactTransport> getContactTransports(Connection txn)
|
public Collection<Endpoint> getEndpoints(Connection txn)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT contactId, transportId, epoch, clockDiff,"
|
String sql = "SELECT contactId, transportId, epoch, clockDiff,"
|
||||||
+ " latency, alice"
|
+ " latency, alice"
|
||||||
+ " FROM contactTransports";
|
+ " FROM endpoints";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<ContactTransport> cts = new ArrayList<ContactTransport>();
|
List<Endpoint> endpoints = new ArrayList<Endpoint>();
|
||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
ContactId c = new ContactId(rs.getInt(1));
|
ContactId c = new ContactId(rs.getInt(1));
|
||||||
TransportId t = new TransportId(rs.getBytes(2));
|
TransportId t = new TransportId(rs.getBytes(2));
|
||||||
@@ -1023,10 +1020,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
long clockDiff = rs.getLong(4);
|
long clockDiff = rs.getLong(4);
|
||||||
long latency = rs.getLong(5);
|
long latency = rs.getLong(5);
|
||||||
boolean alice = rs.getBoolean(6);
|
boolean alice = rs.getBoolean(6);
|
||||||
cts.add(new ContactTransport(c, t, epoch, clockDiff, latency,
|
endpoints.add(new Endpoint(c, t, epoch, clockDiff, latency,
|
||||||
alice));
|
alice));
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(cts);
|
return Collections.unmodifiableList(endpoints);
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -1556,10 +1553,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
String sql = "SELECT ct.contactId, ct.transportId, epoch,"
|
String sql = "SELECT ct.contactId, ct.transportId, epoch,"
|
||||||
+ " clockDiff, latency, alice, period, secret, outgoing,"
|
+ " clockDiff, latency, alice, period, secret, outgoing,"
|
||||||
+ " centre, bitmap"
|
+ " centre, bitmap"
|
||||||
+ " FROM contactTransports AS ct"
|
+ " FROM endpoints AS e"
|
||||||
+ " JOIN secrets AS s"
|
+ " JOIN secrets AS s"
|
||||||
+ " ON ct.contactId = s.contactId"
|
+ " ON e.contactId = s.contactId"
|
||||||
+ " AND ct.transportId = s.transportId";
|
+ " AND e.transportId = s.transportId";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<TemporarySecret> secrets = new ArrayList<TemporarySecret>();
|
List<TemporarySecret> secrets = new ArrayList<TemporarySecret>();
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import net.sf.briar.api.db.event.DatabaseListener;
|
|||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.transport.ConnectionContext;
|
import net.sf.briar.api.transport.ConnectionContext;
|
||||||
import net.sf.briar.api.transport.ConnectionRecogniser;
|
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
import net.sf.briar.util.ByteUtils;
|
import net.sf.briar.util.ByteUtils;
|
||||||
|
|
||||||
@@ -43,11 +43,11 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
// Locking: this
|
// Locking: this
|
||||||
private final Map<ContactTransportKey, TemporarySecret> outgoing;
|
private final Map<EndpointKey, TemporarySecret> outgoing;
|
||||||
// Locking: this
|
// Locking: this
|
||||||
private final Map<ContactTransportKey, TemporarySecret> incomingOld;
|
private final Map<EndpointKey, TemporarySecret> incomingOld;
|
||||||
// Locking: this
|
// Locking: this
|
||||||
private final Map<ContactTransportKey, TemporarySecret> incomingNew;
|
private final Map<EndpointKey, TemporarySecret> incomingNew;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
KeyManagerImpl(CryptoComponent crypto, DatabaseComponent db,
|
KeyManagerImpl(CryptoComponent crypto, DatabaseComponent db,
|
||||||
@@ -57,9 +57,9 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
this.recogniser = recogniser;
|
this.recogniser = recogniser;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.timer = timer;
|
this.timer = timer;
|
||||||
outgoing = new HashMap<ContactTransportKey, TemporarySecret>();
|
outgoing = new HashMap<EndpointKey, TemporarySecret>();
|
||||||
incomingOld = new HashMap<ContactTransportKey, TemporarySecret>();
|
incomingOld = new HashMap<EndpointKey, TemporarySecret>();
|
||||||
incomingNew = new HashMap<ContactTransportKey, TemporarySecret>();
|
incomingNew = new HashMap<EndpointKey, TemporarySecret>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean start() {
|
public synchronized boolean start() {
|
||||||
@@ -97,7 +97,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
Collection<TemporarySecret> secrets) {
|
Collection<TemporarySecret> secrets) {
|
||||||
Collection<TemporarySecret> dead = new ArrayList<TemporarySecret>();
|
Collection<TemporarySecret> dead = new ArrayList<TemporarySecret>();
|
||||||
for(TemporarySecret s : secrets) {
|
for(TemporarySecret s : secrets) {
|
||||||
ContactTransportKey k = new ContactTransportKey(s);
|
EndpointKey k = new EndpointKey(s);
|
||||||
long rotationPeriod = getRotationPeriod(s);
|
long rotationPeriod = getRotationPeriod(s);
|
||||||
long creationTime = getCreationTime(s);
|
long creationTime = getCreationTime(s);
|
||||||
long activationTime = creationTime + s.getClockDifference();
|
long activationTime = creationTime + s.getClockDifference();
|
||||||
@@ -136,7 +136,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
Collection<TemporarySecret> dead) {
|
Collection<TemporarySecret> dead) {
|
||||||
Collection<TemporarySecret> created = new ArrayList<TemporarySecret>();
|
Collection<TemporarySecret> created = new ArrayList<TemporarySecret>();
|
||||||
for(TemporarySecret s : dead) {
|
for(TemporarySecret s : dead) {
|
||||||
ContactTransportKey k = new ContactTransportKey(s);
|
EndpointKey k = new EndpointKey(s);
|
||||||
if(incomingNew.containsKey(k)) throw new IllegalStateException();
|
if(incomingNew.containsKey(k)) throw new IllegalStateException();
|
||||||
byte[] secret = s.getSecret();
|
byte[] secret = s.getSecret();
|
||||||
long period = s.getPeriod();
|
long period = s.getPeriod();
|
||||||
@@ -196,8 +196,8 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getRotationPeriod(ContactTransport s) {
|
private long getRotationPeriod(Endpoint ep) {
|
||||||
return 2 * s.getClockDifference() + s.getLatency();
|
return 2 * ep.getClockDifference() + ep.getLatency();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getCreationTime(TemporarySecret s) {
|
private long getCreationTime(TemporarySecret s) {
|
||||||
@@ -221,7 +221,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
|
|
||||||
public synchronized ConnectionContext getConnectionContext(ContactId c,
|
public synchronized ConnectionContext getConnectionContext(ContactId c,
|
||||||
TransportId t) {
|
TransportId t) {
|
||||||
TemporarySecret s = outgoing.get(new ContactTransportKey(c, t));
|
TemporarySecret s = outgoing.get(new EndpointKey(c, t));
|
||||||
if(s == null) return null;
|
if(s == null) return null;
|
||||||
long connection;
|
long connection;
|
||||||
try {
|
try {
|
||||||
@@ -234,11 +234,10 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
return new ConnectionContext(c, t, secret, connection, s.getAlice());
|
return new ConnectionContext(c, t, secret, connection, s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void contactTransportAdded(ContactTransport ct,
|
public synchronized void endpointAdded(Endpoint ep, byte[] initialSecret) {
|
||||||
byte[] initialSecret) {
|
|
||||||
long now = clock.currentTimeMillis();
|
long now = clock.currentTimeMillis();
|
||||||
long rotationPeriod = getRotationPeriod(ct);
|
long rotationPeriod = getRotationPeriod(ep);
|
||||||
long elapsed = now - ct.getEpoch();
|
long elapsed = now - ep.getEpoch();
|
||||||
long currentPeriod = elapsed / rotationPeriod;
|
long currentPeriod = elapsed / rotationPeriod;
|
||||||
if(currentPeriod < 1) throw new IllegalArgumentException();
|
if(currentPeriod < 1) throw new IllegalArgumentException();
|
||||||
// Derive the two current incoming secrets
|
// Derive the two current incoming secrets
|
||||||
@@ -251,15 +250,15 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
}
|
}
|
||||||
secret2 = crypto.deriveNextSecret(secret1, currentPeriod);
|
secret2 = crypto.deriveNextSecret(secret1, currentPeriod);
|
||||||
// One of the incoming secrets is the current outgoing secret
|
// One of the incoming secrets is the current outgoing secret
|
||||||
ContactTransportKey k = new ContactTransportKey(ct);
|
EndpointKey k = new EndpointKey(ep);
|
||||||
TemporarySecret s1, s2, dupe;
|
TemporarySecret s1, s2, dupe;
|
||||||
s1 = new TemporarySecret(ct, currentPeriod - 1, secret1);
|
s1 = new TemporarySecret(ep, currentPeriod - 1, secret1);
|
||||||
dupe = incomingOld.put(k, s1);
|
dupe = incomingOld.put(k, s1);
|
||||||
if(dupe != null) throw new IllegalStateException();
|
if(dupe != null) throw new IllegalStateException();
|
||||||
s2 = new TemporarySecret(ct, currentPeriod, secret2);
|
s2 = new TemporarySecret(ep, currentPeriod, secret2);
|
||||||
dupe = incomingNew.put(k, s2);
|
dupe = incomingNew.put(k, s2);
|
||||||
if(dupe != null) throw new IllegalStateException();
|
if(dupe != null) throw new IllegalStateException();
|
||||||
if(elapsed % rotationPeriod < ct.getClockDifference()) {
|
if(elapsed % rotationPeriod < ep.getClockDifference()) {
|
||||||
// The outgoing secret is the newer incoming secret
|
// The outgoing secret is the newer incoming secret
|
||||||
dupe = outgoing.put(k, s2);
|
dupe = outgoing.put(k, s2);
|
||||||
if(dupe != null) throw new IllegalStateException();
|
if(dupe != null) throw new IllegalStateException();
|
||||||
@@ -338,18 +337,17 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ContactTransportKey {
|
private static class EndpointKey {
|
||||||
|
|
||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
|
|
||||||
private ContactTransportKey(ContactId contactId,
|
private EndpointKey(ContactId contactId, TransportId transportId) {
|
||||||
TransportId transportId) {
|
|
||||||
this.contactId = contactId;
|
this.contactId = contactId;
|
||||||
this.transportId = transportId;
|
this.transportId = transportId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContactTransportKey(ContactTransport ct) {
|
private EndpointKey(Endpoint ct) {
|
||||||
this(ct.getContactId(), ct.getTransportId());
|
this(ct.getContactId(), ct.getTransportId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,8 +358,8 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if(o instanceof ContactTransportKey) {
|
if(o instanceof EndpointKey) {
|
||||||
ContactTransportKey k = (ContactTransportKey) o;
|
EndpointKey k = (EndpointKey) o;
|
||||||
return contactId.equals(k.contactId) &&
|
return contactId.equals(k.contactId) &&
|
||||||
transportId.equals(k.transportId);
|
transportId.equals(k.transportId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import net.sf.briar.api.Rating;
|
|||||||
import net.sf.briar.api.TransportProperties;
|
import net.sf.briar.api.TransportProperties;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
import net.sf.briar.api.db.DatabaseComponent;
|
||||||
import net.sf.briar.api.db.NoSuchContactException;
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.NoSuchContactTransportException;
|
import net.sf.briar.api.db.NoSuchTransportException;
|
||||||
import net.sf.briar.api.db.event.ContactAddedEvent;
|
import net.sf.briar.api.db.event.ContactAddedEvent;
|
||||||
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||||
import net.sf.briar.api.db.event.DatabaseListener;
|
import net.sf.briar.api.db.event.DatabaseListener;
|
||||||
@@ -33,7 +33,7 @@ import net.sf.briar.api.protocol.SubscriptionUpdate;
|
|||||||
import net.sf.briar.api.protocol.Transport;
|
import net.sf.briar.api.protocol.Transport;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.protocol.TransportUpdate;
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
@@ -55,7 +55,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
private final Group group;
|
private final Group group;
|
||||||
private final TransportId transportId;
|
private final TransportId transportId;
|
||||||
private final Collection<Transport> transports;
|
private final Collection<Transport> transports;
|
||||||
private final ContactTransport contactTransport;
|
private final Endpoint contactTransport;
|
||||||
private final TemporarySecret temporarySecret;
|
private final TemporarySecret temporarySecret;
|
||||||
|
|
||||||
public DatabaseComponentTest() {
|
public DatabaseComponentTest() {
|
||||||
@@ -79,7 +79,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
Collections.singletonMap("foo", "bar"));
|
Collections.singletonMap("foo", "bar"));
|
||||||
Transport transport = new Transport(transportId, properties);
|
Transport transport = new Transport(transportId, properties);
|
||||||
transports = Collections.singletonList(transport);
|
transports = Collections.singletonList(transport);
|
||||||
contactTransport = new ContactTransport(contactId, transportId, 123L,
|
contactTransport = new Endpoint(contactId, transportId, 123L,
|
||||||
234L, 345L, true);
|
234L, 345L, true);
|
||||||
temporarySecret = new TemporarySecret(contactId, transportId, 1L, 2L,
|
temporarySecret = new TemporarySecret(contactId, transportId, 1L, 2L,
|
||||||
3L, false, 4L, new byte[32], 5L, 6L, new byte[4]);
|
3L, false, 4L, new byte[32], 5L, 6L, new byte[4]);
|
||||||
@@ -494,7 +494,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
shutdown);
|
shutdown);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.addContactTransport(contactTransport);
|
db.addEndpoint(contactTransport);
|
||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
@@ -589,7 +589,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
// Check whether the contact transport is in the DB (which it's not)
|
// Check whether the contact transport is in the DB (which it's not)
|
||||||
exactly(2).of(database).startTransaction();
|
exactly(2).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
exactly(2).of(database).containsContactTransport(txn, contactId,
|
exactly(2).of(database).containsEndpoint(txn, contactId,
|
||||||
transportId);
|
transportId);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
exactly(2).of(database).abortTransaction(txn);
|
exactly(2).of(database).abortTransaction(txn);
|
||||||
@@ -600,12 +600,12 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
try {
|
try {
|
||||||
db.incrementConnectionCounter(contactId, transportId, 0L);
|
db.incrementConnectionCounter(contactId, transportId, 0L);
|
||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactTransportException expected) {}
|
} catch(NoSuchTransportException expected) {}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.setConnectionWindow(contactId, transportId, 0L, 0L, new byte[4]);
|
db.setConnectionWindow(contactId, transportId, 0L, 0L, new byte[4]);
|
||||||
fail();
|
fail();
|
||||||
} catch(NoSuchContactTransportException expected) {}
|
} catch(NoSuchTransportException expected) {}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -1427,7 +1427,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
// addSecrets()
|
// addSecrets()
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
oneOf(database).containsContactTransport(txn, contactId,
|
oneOf(database).containsEndpoint(txn, contactId,
|
||||||
transportId);
|
transportId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(database).addSecrets(txn,
|
oneOf(database).addSecrets(txn,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import net.sf.briar.api.protocol.Message;
|
|||||||
import net.sf.briar.api.protocol.MessageId;
|
import net.sf.briar.api.protocol.MessageId;
|
||||||
import net.sf.briar.api.protocol.Transport;
|
import net.sf.briar.api.protocol.Transport;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.api.transport.TemporarySecret;
|
import net.sf.briar.api.transport.TemporarySecret;
|
||||||
|
|
||||||
import org.apache.commons.io.FileSystemUtils;
|
import org.apache.commons.io.FileSystemUtils;
|
||||||
@@ -1562,7 +1562,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
long outgoing1 = 456L, centre1 = 567L;
|
long outgoing1 = 456L, centre1 = 567L;
|
||||||
long outgoing2 = 678L, centre2 = 789L;
|
long outgoing2 = 678L, centre2 = 789L;
|
||||||
long outgoing3 = 890L, centre3 = 901L;
|
long outgoing3 = 890L, centre3 = 901L;
|
||||||
ContactTransport ct = new ContactTransport(contactId, transportId,
|
Endpoint ct = new Endpoint(contactId, transportId,
|
||||||
epoch, clockDiff, latency, alice);
|
epoch, clockDiff, latency, alice);
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] secret1 = new byte[32], bitmap1 = new byte[4];
|
byte[] secret1 = new byte[32], bitmap1 = new byte[4];
|
||||||
@@ -1592,7 +1592,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
|
|
||||||
// Add the contact transport and the first two secrets
|
// Add the contact transport and the first two secrets
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn));
|
||||||
db.addContactTransport(txn, ct);
|
db.addEndpoint(txn, ct);
|
||||||
db.addSecrets(txn, Arrays.asList(s1, s2));
|
db.addSecrets(txn, Arrays.asList(s1, s2));
|
||||||
|
|
||||||
// Retrieve the first two secrets
|
// Retrieve the first two secrets
|
||||||
@@ -1671,7 +1671,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
long epoch = 123L, clockDiff = 234L, latency = 345L;
|
long epoch = 123L, clockDiff = 234L, latency = 345L;
|
||||||
boolean alice = false;
|
boolean alice = false;
|
||||||
long period = 456L, outgoing = 567L, centre = 678L;
|
long period = 456L, outgoing = 567L, centre = 678L;
|
||||||
ContactTransport ct = new ContactTransport(contactId, transportId,
|
Endpoint ct = new Endpoint(contactId, transportId,
|
||||||
epoch, clockDiff, latency, alice);
|
epoch, clockDiff, latency, alice);
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] secret = new byte[32], bitmap = new byte[4];
|
byte[] secret = new byte[32], bitmap = new byte[4];
|
||||||
@@ -1685,7 +1685,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
|
|
||||||
// Add the contact transport and the temporary secret
|
// Add the contact transport and the temporary secret
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn));
|
||||||
db.addContactTransport(txn, ct);
|
db.addEndpoint(txn, ct);
|
||||||
db.addSecrets(txn, Arrays.asList(s));
|
db.addSecrets(txn, Arrays.asList(s));
|
||||||
|
|
||||||
// Retrieve the secret
|
// Retrieve the secret
|
||||||
@@ -1726,7 +1726,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
long epoch = 123L, clockDiff = 234L, latency = 345L;
|
long epoch = 123L, clockDiff = 234L, latency = 345L;
|
||||||
boolean alice = false;
|
boolean alice = false;
|
||||||
long period = 456L, outgoing = 567L, centre = 678L;
|
long period = 456L, outgoing = 567L, centre = 678L;
|
||||||
ContactTransport ct = new ContactTransport(contactId, transportId,
|
Endpoint ct = new Endpoint(contactId, transportId,
|
||||||
epoch, clockDiff, latency, alice);
|
epoch, clockDiff, latency, alice);
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] secret = new byte[32], bitmap = new byte[4];
|
byte[] secret = new byte[32], bitmap = new byte[4];
|
||||||
@@ -1740,7 +1740,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
|
|
||||||
// Add the contact transport and the temporary secret
|
// Add the contact transport and the temporary secret
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn));
|
||||||
db.addContactTransport(txn, ct);
|
db.addEndpoint(txn, ct);
|
||||||
db.addSecrets(txn, Arrays.asList(s));
|
db.addSecrets(txn, Arrays.asList(s));
|
||||||
|
|
||||||
// Retrieve the secret
|
// Retrieve the secret
|
||||||
@@ -1797,27 +1797,27 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
boolean alice1 = true, alice2 = false;
|
boolean alice1 = true, alice2 = false;
|
||||||
TransportId transportId1 = new TransportId(TestUtils.getRandomId());
|
TransportId transportId1 = new TransportId(TestUtils.getRandomId());
|
||||||
TransportId transportId2 = new TransportId(TestUtils.getRandomId());
|
TransportId transportId2 = new TransportId(TestUtils.getRandomId());
|
||||||
ContactTransport ct1 = new ContactTransport(contactId, transportId1,
|
Endpoint ct1 = new Endpoint(contactId, transportId1,
|
||||||
epoch1, clockDiff1, latency1, alice1);
|
epoch1, clockDiff1, latency1, alice1);
|
||||||
ContactTransport ct2 = new ContactTransport(contactId, transportId2,
|
Endpoint ct2 = new Endpoint(contactId, transportId2,
|
||||||
epoch2, clockDiff2, latency2, alice2);
|
epoch2, clockDiff2, latency2, alice2);
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Initially there should be no contact transports in the database
|
// Initially there should be no contact transports in the database
|
||||||
assertEquals(Collections.emptyList(), db.getContactTransports(txn));
|
assertEquals(Collections.emptyList(), db.getEndpoints(txn));
|
||||||
|
|
||||||
// Add a contact and the contact transports
|
// Add a contact and the contact transports
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn));
|
||||||
db.addContactTransport(txn, ct1);
|
db.addEndpoint(txn, ct1);
|
||||||
db.addContactTransport(txn, ct2);
|
db.addEndpoint(txn, ct2);
|
||||||
|
|
||||||
// Retrieve the contact transports
|
// Retrieve the contact transports
|
||||||
Collection<ContactTransport> cts = db.getContactTransports(txn);
|
Collection<Endpoint> cts = db.getEndpoints(txn);
|
||||||
assertEquals(2, cts.size());
|
assertEquals(2, cts.size());
|
||||||
boolean foundFirst = false, foundSecond = false;
|
boolean foundFirst = false, foundSecond = false;
|
||||||
for(ContactTransport ct : cts) {
|
for(Endpoint ct : cts) {
|
||||||
assertEquals(contactId, ct.getContactId());
|
assertEquals(contactId, ct.getContactId());
|
||||||
if(ct.getTransportId().equals(transportId1)) {
|
if(ct.getTransportId().equals(transportId1)) {
|
||||||
assertEquals(epoch1, ct.getEpoch());
|
assertEquals(epoch1, ct.getEpoch());
|
||||||
@@ -1840,7 +1840,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
|
|
||||||
// Removing the contact should remove the contact transports
|
// Removing the contact should remove the contact transports
|
||||||
db.removeContact(txn, contactId);
|
db.removeContact(txn, contactId);
|
||||||
assertEquals(Collections.emptyList(), db.getContactTransports(txn));
|
assertEquals(Collections.emptyList(), db.getEndpoints(txn));
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
db.close();
|
db.close();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import net.sf.briar.api.transport.ConnectionReaderFactory;
|
|||||||
import net.sf.briar.api.transport.ConnectionRecogniser;
|
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||||
import net.sf.briar.api.transport.ConnectionRegistry;
|
import net.sf.briar.api.transport.ConnectionRegistry;
|
||||||
import net.sf.briar.api.transport.ConnectionWriterFactory;
|
import net.sf.briar.api.transport.ConnectionWriterFactory;
|
||||||
import net.sf.briar.api.transport.ContactTransport;
|
import net.sf.briar.api.transport.Endpoint;
|
||||||
import net.sf.briar.clock.ClockModule;
|
import net.sf.briar.clock.ClockModule;
|
||||||
import net.sf.briar.crypto.CryptoModule;
|
import net.sf.briar.crypto.CryptoModule;
|
||||||
import net.sf.briar.db.DatabaseModule;
|
import net.sf.briar.db.DatabaseModule;
|
||||||
@@ -107,10 +107,10 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
|
|||||||
km.start();
|
km.start();
|
||||||
// Add Bob as a contact
|
// Add Bob as a contact
|
||||||
ContactId contactId = db.addContact();
|
ContactId contactId = db.addContact();
|
||||||
ContactTransport ct = new ContactTransport(contactId, transportId,
|
Endpoint ct = new Endpoint(contactId, transportId,
|
||||||
epoch, CLOCK_DIFFERENCE, LATENCY, true);
|
epoch, CLOCK_DIFFERENCE, LATENCY, true);
|
||||||
db.addContactTransport(ct);
|
db.addEndpoint(ct);
|
||||||
km.contactTransportAdded(ct, initialSecret.clone());
|
km.endpointAdded(ct, initialSecret.clone());
|
||||||
// Send Bob a message
|
// Send Bob a message
|
||||||
String subject = "Hello";
|
String subject = "Hello";
|
||||||
byte[] body = "Hi Bob!".getBytes("UTF-8");
|
byte[] body = "Hi Bob!".getBytes("UTF-8");
|
||||||
@@ -151,10 +151,10 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
|
|||||||
km.start();
|
km.start();
|
||||||
// Add Alice as a contact
|
// Add Alice as a contact
|
||||||
ContactId contactId = db.addContact();
|
ContactId contactId = db.addContact();
|
||||||
ContactTransport ct = new ContactTransport(contactId, transportId,
|
Endpoint ct = new Endpoint(contactId, transportId,
|
||||||
epoch, CLOCK_DIFFERENCE, LATENCY, false);
|
epoch, CLOCK_DIFFERENCE, LATENCY, false);
|
||||||
db.addContactTransport(ct);
|
db.addEndpoint(ct);
|
||||||
km.contactTransportAdded(ct, initialSecret.clone());
|
km.endpointAdded(ct, initialSecret.clone());
|
||||||
// Set up a database listener
|
// Set up a database listener
|
||||||
MessageListener listener = new MessageListener();
|
MessageListener listener = new MessageListener();
|
||||||
db.addListener(listener);
|
db.addListener(listener);
|
||||||
|
|||||||
Reference in New Issue
Block a user