mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Merge branch '279-create-client-state' into 'master'
Create local state for clients at startup. #279 Most of the clients we've written so far use private groups shared with individual contacts and/or a local group that's not shared with anyone. To make it easier to ensure that the necessary groups exist when we need them, this patch allows clients to register startup hooks for creating their local state. Fixes #279. See merge request !131
This commit is contained in:
@@ -93,10 +93,8 @@ public class AndroidModule {
|
||||
AndroidNotificationManager provideAndroidNotificationManager(
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
AndroidNotificationManagerImpl notificationManager) {
|
||||
lifecycleManager.register(notificationManager);
|
||||
lifecycleManager.registerService(notificationManager);
|
||||
eventBus.addListener(notificationManager);
|
||||
|
||||
return notificationManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
briar-api/src/org/briarproject/api/clients/Client.java
Normal file
12
briar-api/src/org/briarproject/api/clients/Client.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package org.briarproject.api.clients;
|
||||
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Transaction;
|
||||
|
||||
public interface Client {
|
||||
|
||||
/**
|
||||
* Called at startup to create any local state needed by the client.
|
||||
*/
|
||||
void createLocalState(Transaction txn) throws DbException;
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import org.briarproject.api.sync.Group;
|
||||
|
||||
public interface PrivateGroupFactory {
|
||||
|
||||
/** Creates a group that is not shared with any contacts. */
|
||||
Group createLocalGroup(ClientId clientId);
|
||||
|
||||
/** Creates a group for the given client to share with the given contact. */
|
||||
Group createPrivateGroup(ClientId clientId, Contact contact);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public interface DatabaseComponent {
|
||||
* <p/>
|
||||
* This method acquires locks, so it must not be called while holding a
|
||||
* lock.
|
||||
*
|
||||
* @param readOnly true if the transaction will only be used for reading.
|
||||
*/
|
||||
Transaction startTransaction(boolean readOnly) throws DbException;
|
||||
@@ -90,13 +91,27 @@ public interface DatabaseComponent {
|
||||
void addTransportKeys(Transaction txn, ContactId c, TransportKeys k)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the database contains the given contact for the given
|
||||
* local pseudonym.
|
||||
*/
|
||||
boolean containsContact(Transaction txn, AuthorId remote, AuthorId local)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the database contains the given group.
|
||||
*/
|
||||
boolean containsGroup(Transaction txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Deletes the message with the given ID. The message ID and any other
|
||||
* associated data are not deleted.
|
||||
*/
|
||||
void deleteMessage(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/** Deletes any metadata associated with the given message. */
|
||||
/**
|
||||
* Deletes any metadata associated with the given message.
|
||||
*/
|
||||
void deleteMessageMetadata(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
@@ -162,13 +177,6 @@ public interface DatabaseComponent {
|
||||
Collection<ContactId> getContacts(Transaction txn, AuthorId a)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the database contains the given contact for the given
|
||||
* local pseudonym.
|
||||
*/
|
||||
boolean containsContact(Transaction txn, AuthorId remote, AuthorId local)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the unique ID for this device.
|
||||
* <p/>
|
||||
@@ -359,7 +367,7 @@ public interface DatabaseComponent {
|
||||
* Marks the given contact as active or inactive.
|
||||
*/
|
||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||
throws DbException;
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given message as shared or unshared.
|
||||
|
||||
@@ -1,32 +1,49 @@
|
||||
package org.briarproject.api.lifecycle;
|
||||
|
||||
import org.briarproject.api.clients.Client;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* Manages the lifecycle of the app, starting and stopping {@link Service
|
||||
* Services}, shutting down {@link java.util.concurrent.ExecutorService
|
||||
* Manages the lifecycle of the app, starting {@link
|
||||
* org.briarproject.api.clients.Client Clients}, starting and stopping {@link
|
||||
* Service Services}, shutting down {@link java.util.concurrent.ExecutorService
|
||||
* ExecutorServices}, and opening and closing the {@link
|
||||
* org.briarproject.api.db.DatabaseComponent DatabaseComponent}.
|
||||
*/
|
||||
public interface LifecycleManager {
|
||||
|
||||
/** The result of calling {@link LifecycleManager#startServices()}. */
|
||||
enum StartResult { ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS }
|
||||
/**
|
||||
* The result of calling {@link LifecycleManager#startServices()}.
|
||||
*/
|
||||
enum StartResult {
|
||||
ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS
|
||||
}
|
||||
|
||||
/** Registers a {@link Service} to be started and stopped. */
|
||||
public void register(Service s);
|
||||
/**
|
||||
* Registers a {@link Service} to be started and stopped.
|
||||
*/
|
||||
void registerService(Service s);
|
||||
|
||||
/**
|
||||
* Registers a {@link org.briarproject.api.clients.Client Client} to be
|
||||
* started.
|
||||
*/
|
||||
void registerClient(Client c);
|
||||
|
||||
/**
|
||||
* Registers an {@link java.util.concurrent.ExecutorService ExecutorService}
|
||||
* to be shut down.
|
||||
*/
|
||||
public void registerForShutdown(ExecutorService e);
|
||||
void registerForShutdown(ExecutorService e);
|
||||
|
||||
/**
|
||||
* Starts any registered {@link Service Services} and opens the {@link
|
||||
* org.briarproject.api.db.DatabaseComponent DatabaseComponent}.
|
||||
* Opens the {@link org.briarproject.api.db.DatabaseComponent
|
||||
* DatabaseComponent} and starts any registered {@link
|
||||
* org.briarproject.api.clients.Client Clients} and {@link Service
|
||||
* Services}.
|
||||
*/
|
||||
public StartResult startServices();
|
||||
StartResult startServices();
|
||||
|
||||
/**
|
||||
* Stops any registered {@link Service Services}, shuts down any
|
||||
@@ -34,20 +51,21 @@ public interface LifecycleManager {
|
||||
* and closes the {@link org.briarproject.api.db.DatabaseComponent
|
||||
* DatabaseComponent}.
|
||||
*/
|
||||
public void stopServices();
|
||||
void stopServices();
|
||||
|
||||
/**
|
||||
* Waits for the {@link org.briarproject.api.db.DatabaseComponent
|
||||
* DatabaseComponent} to be opened before returning.
|
||||
*/
|
||||
public void waitForDatabase() throws InterruptedException;
|
||||
void waitForDatabase() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Waits for the {@link org.briarproject.api.db.DatabaseComponent
|
||||
* DatabaseComponent} to be opened and all registered {@link Service
|
||||
* DatabaseComponent} to be opened and all registered {@link
|
||||
* org.briarproject.api.clients.Client Clients} and {@link Service
|
||||
* Services} to start before returning.
|
||||
*/
|
||||
public void waitForStartup() throws InterruptedException;
|
||||
void waitForStartup() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Waits for all registered {@link Service Services} to stop, all
|
||||
@@ -55,5 +73,5 @@ public interface LifecycleManager {
|
||||
* to shut down, and the {@link org.briarproject.api.db.DatabaseComponent
|
||||
* DatabaseComponent} to be closed before returning.
|
||||
*/
|
||||
public void waitForShutdown() throws InterruptedException;
|
||||
void waitForShutdown() throws InterruptedException;
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import javax.inject.Inject;
|
||||
|
||||
class PrivateGroupFactoryImpl implements PrivateGroupFactory {
|
||||
|
||||
private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
|
||||
|
||||
private final GroupFactory groupFactory;
|
||||
private final ClientHelper clientHelper;
|
||||
|
||||
@@ -26,6 +28,11 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory {
|
||||
this.clientHelper = clientHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group createLocalGroup(ClientId clientId) {
|
||||
return groupFactory.createGroup(clientId, LOCAL_GROUP_DESCRIPTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group createPrivateGroup(ClientId clientId, Contact contact) {
|
||||
AuthorId local = contact.getLocalAuthorId();
|
||||
|
||||
@@ -231,6 +231,20 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
db.addTransportKeys(txn, c, k);
|
||||
}
|
||||
|
||||
public boolean containsContact(Transaction transaction, AuthorId remote,
|
||||
AuthorId local) throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsLocalAuthor(txn, local))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
return db.containsContact(txn, remote, local);
|
||||
}
|
||||
|
||||
public boolean containsGroup(Transaction transaction, GroupId g)
|
||||
throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
return db.containsGroup(txn, g);
|
||||
}
|
||||
|
||||
public void deleteMessage(Transaction transaction, MessageId m)
|
||||
throws DbException {
|
||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||
@@ -345,14 +359,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
return db.getContacts(txn, a);
|
||||
}
|
||||
|
||||
public boolean containsContact(Transaction transaction, AuthorId remote,
|
||||
AuthorId local) throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsLocalAuthor(txn, local))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
return db.containsContact(txn, remote, local);
|
||||
}
|
||||
|
||||
public DeviceId getDeviceId(Transaction transaction) throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
return db.getDeviceId(txn);
|
||||
|
||||
@@ -3,14 +3,13 @@ package org.briarproject.forum;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.data.MetadataParser;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.forum.ForumSharingManager;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
@@ -73,9 +72,11 @@ public class ForumModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
ForumSharingManager provideForumSharingManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
ValidationManager validationManager,
|
||||
ForumSharingManagerImpl forumSharingManager) {
|
||||
lifecycleManager.registerClient(forumSharingManager);
|
||||
contactManager.registerAddContactHook(forumSharingManager);
|
||||
contactManager.registerRemoveContactHook(forumSharingManager);
|
||||
validationManager.registerIncomingMessageHook(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.forum;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.PrivateGroupFactory;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
@@ -43,15 +44,13 @@ import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
|
||||
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
|
||||
class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
||||
RemoveContactHook, IncomingMessageHook {
|
||||
class ForumSharingManagerImpl implements ForumSharingManager, Client,
|
||||
AddContactHook, RemoveContactHook, IncomingMessageHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
"cd11a5d04dccd9e2931d6fc3df456313"
|
||||
+ "63bb3e9d9d0e9405fccdb051f41f5449"));
|
||||
|
||||
private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final ForumManager forumManager;
|
||||
private final ClientHelper clientHelper;
|
||||
@@ -73,8 +72,14 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.random = random;
|
||||
this.clock = clock;
|
||||
localGroup = groupFactory.createGroup(CLIENT_ID,
|
||||
LOCAL_GROUP_DESCRIPTOR);
|
||||
localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLocalState(Transaction txn) throws DbException {
|
||||
db.addGroup(txn, localGroup);
|
||||
// Ensure we've set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,6 +87,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
||||
try {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
// Return if we've already set things up for this contact
|
||||
if (db.containsGroup(txn, g.getId())) return;
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||
@@ -297,8 +304,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
|
||||
|
||||
private List<Forum> getForumsSharedWithAllContacts(Transaction txn)
|
||||
throws DbException, FormatException {
|
||||
// Ensure the local group exists
|
||||
db.addGroup(txn, localGroup);
|
||||
// Find the latest update in the local group
|
||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), true);
|
||||
if (latest == null) return Collections.emptyList();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.introduction;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.MessageQueueManager;
|
||||
import org.briarproject.api.clients.PrivateGroupFactory;
|
||||
@@ -31,7 +32,6 @@ import org.briarproject.api.introduction.SessionId;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
@@ -82,14 +82,13 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE
|
||||
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
|
||||
|
||||
class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
implements IntroductionManager, AddContactHook, RemoveContactHook {
|
||||
implements IntroductionManager, Client, AddContactHook,
|
||||
RemoveContactHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
"23b1897c198a90ae75b976ac023d0f32"
|
||||
+ "80ca67b12f2346b2c23a34f34e2434c3"));
|
||||
|
||||
private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(IntroductionManagerImpl.class.getName());
|
||||
|
||||
@@ -104,8 +103,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
@Inject
|
||||
IntroductionManagerImpl(DatabaseComponent db,
|
||||
MessageQueueManager messageQueueManager,
|
||||
ClientHelper clientHelper, GroupFactory groupFactory,
|
||||
PrivateGroupFactory privateGroupFactory,
|
||||
ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory,
|
||||
MetadataEncoder metadataEncoder, MetadataParser metadataParser,
|
||||
CryptoComponent cryptoComponent,
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
@@ -117,6 +115,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
this.messageQueueManager = messageQueueManager;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.metadataEncoder = metadataEncoder;
|
||||
// TODO: Inject these dependencies for easier testing
|
||||
this.introducerManager =
|
||||
new IntroducerManager(this, clientHelper, clock,
|
||||
cryptoComponent);
|
||||
@@ -124,8 +123,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
new IntroduceeManager(db, this, clientHelper, clock,
|
||||
cryptoComponent, transportPropertyManager,
|
||||
authorFactory, contactManager);
|
||||
localGroup =
|
||||
groupFactory.createGroup(CLIENT_ID, LOCAL_GROUP_DESCRIPTOR);
|
||||
localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,11 +131,21 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
return CLIENT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLocalState(Transaction txn) throws DbException {
|
||||
db.addGroup(txn, localGroup);
|
||||
// Ensure we've set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
try {
|
||||
// create an introduction group for sending introduction messages
|
||||
// Create an introduction group for sending introduction messages
|
||||
Group g = getIntroductionGroup(c);
|
||||
// Return if we've already set things up for this contact
|
||||
if (db.containsGroup(txn, g.getId())) return;
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||
// Attach the contact ID to the group
|
||||
@@ -169,7 +177,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
introducerManager.abort(txn, d);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -189,9 +196,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
protected void incomingMessage(Transaction txn, Message m, BdfList body,
|
||||
BdfDictionary message) throws DbException {
|
||||
|
||||
// add local group for engine states to make sure it exists
|
||||
db.addGroup(txn, localGroup);
|
||||
|
||||
// Get message data and type
|
||||
GroupId groupId = m.getGroupId();
|
||||
message.put(GROUP_ID, groupId);
|
||||
@@ -265,15 +269,13 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
public void makeIntroduction(Contact c1, Contact c2, String msg)
|
||||
throws DbException, FormatException {
|
||||
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// add local group for session states to make sure it exists
|
||||
db.addGroup(txn, getLocalGroup());
|
||||
introducerManager.makeIntroduction(txn, c1, c2, msg);
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
introducerManager.makeIntroduction(txn, c1, c2, msg);
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -468,7 +470,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
}
|
||||
if (LOG.isLoggable(WARNING)) {
|
||||
LOG.warning(
|
||||
"No session state found for this message with session ID " +
|
||||
"No session state found for message with session ID " +
|
||||
Arrays.hashCode(sessionId));
|
||||
}
|
||||
throw new FormatException();
|
||||
@@ -505,5 +507,4 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
||||
db.deleteMessage(txn, messageId);
|
||||
db.deleteMessageMetadata(txn, messageId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.briarproject.api.clients.MessageQueueManager;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.introduction.IntroductionManager;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -41,15 +42,17 @@ public class IntroductionModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
IntroductionManager getIntroductionManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
MessageQueueManager messageQueueManager,
|
||||
IntroductionManagerImpl introductionManager) {
|
||||
|
||||
lifecycleManager.registerClient(introductionManager);
|
||||
contactManager.registerAddContactHook(introductionManager);
|
||||
contactManager.registerRemoveContactHook(introductionManager);
|
||||
messageQueueManager
|
||||
.registerIncomingMessageHook(introductionManager.getClientId(),
|
||||
introductionManager);
|
||||
messageQueueManager.registerIncomingMessageHook(
|
||||
introductionManager.getClientId(),
|
||||
introductionManager);
|
||||
|
||||
return introductionManager;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package org.briarproject.lifecycle;
|
||||
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.ShutdownEvent;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -31,8 +33,9 @@ class LifecycleManagerImpl implements LifecycleManager {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final EventBus eventBus;
|
||||
private final Collection<Service> services;
|
||||
private final Collection<ExecutorService> executors;
|
||||
private final List<Service> services;
|
||||
private final List<Client> clients;
|
||||
private final List<ExecutorService> executors;
|
||||
private final Semaphore startStopSemaphore = new Semaphore(1);
|
||||
private final CountDownLatch dbLatch = new CountDownLatch(1);
|
||||
private final CountDownLatch startupLatch = new CountDownLatch(1);
|
||||
@@ -43,15 +46,22 @@ class LifecycleManagerImpl implements LifecycleManager {
|
||||
this.db = db;
|
||||
this.eventBus = eventBus;
|
||||
services = new CopyOnWriteArrayList<Service>();
|
||||
clients = new CopyOnWriteArrayList<Client>();
|
||||
executors = new CopyOnWriteArrayList<ExecutorService>();
|
||||
}
|
||||
|
||||
public void register(Service s) {
|
||||
public void registerService(Service s) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Registering service " + s.getClass().getName());
|
||||
services.add(s);
|
||||
}
|
||||
|
||||
public void registerClient(Client c) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Registering client " + c.getClass().getName());
|
||||
clients.add(c);
|
||||
}
|
||||
|
||||
public void registerForShutdown(ExecutorService e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Registering executor " + e.getClass().getName());
|
||||
@@ -74,15 +84,28 @@ class LifecycleManagerImpl implements LifecycleManager {
|
||||
else LOG.info("Creating database took " + duration + " ms");
|
||||
}
|
||||
dbLatch.countDown();
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
for (Client c : clients) {
|
||||
start = System.currentTimeMillis();
|
||||
c.createLocalState(txn);
|
||||
duration = System.currentTimeMillis() - start;
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Starting " + c.getClass().getName()
|
||||
+ " took " + duration + " ms");
|
||||
}
|
||||
}
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
for (Service s : services) {
|
||||
start = System.currentTimeMillis();
|
||||
boolean started = s.start();
|
||||
duration = System.currentTimeMillis() - start;
|
||||
if (!started) {
|
||||
if (LOG.isLoggable(WARNING)) {
|
||||
String name = s.getClass().getName();
|
||||
LOG.warning(name + " did not start");
|
||||
}
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.warning(s.getClass().getName() + " did not start");
|
||||
return SERVICE_ERROR;
|
||||
}
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.messaging;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.PrivateGroupFactory;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
@@ -28,7 +29,7 @@ import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
class MessagingManagerImpl implements MessagingManager, AddContactHook,
|
||||
class MessagingManagerImpl implements MessagingManager, Client, AddContactHook,
|
||||
RemoveContactHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
@@ -47,11 +48,19 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLocalState(Transaction txn) throws DbException {
|
||||
// Ensure we've set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
try {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
// Return if we've already set things up for this contact
|
||||
if (db.containsGroup(txn, g.getId())) return;
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.messaging;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
@@ -43,8 +44,10 @@ public class MessagingModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
MessagingManager getMessagingManager(ContactManager contactManager,
|
||||
MessagingManager getMessagingManager(LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
MessagingManagerImpl messagingManager) {
|
||||
lifecycleManager.registerClient(messagingManager);
|
||||
contactManager.registerAddContactHook(messagingManager);
|
||||
contactManager.registerRemoveContactHook(messagingManager);
|
||||
return messagingManager;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class PluginsModule {
|
||||
@Singleton
|
||||
PluginManager getPluginManager(LifecycleManager lifecycleManager,
|
||||
PluginManagerImpl pluginManager) {
|
||||
lifecycleManager.register(pluginManager);
|
||||
lifecycleManager.registerService(pluginManager);
|
||||
return pluginManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.properties;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
@@ -36,8 +37,10 @@ public class PropertiesModule {
|
||||
|
||||
@Provides @Singleton
|
||||
TransportPropertyManager getTransportPropertyManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManagerImpl transportPropertyManager) {
|
||||
lifecycleManager.registerClient(transportPropertyManager);
|
||||
contactManager.registerAddContactHook(transportPropertyManager);
|
||||
contactManager.registerRemoveContactHook(transportPropertyManager);
|
||||
return transportPropertyManager;
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.properties;
|
||||
import org.briarproject.api.DeviceId;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.PrivateGroupFactory;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
@@ -13,13 +14,11 @@ import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.NoSuchGroupException;
|
||||
import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
@@ -34,14 +33,12 @@ import java.util.Map.Entry;
|
||||
import javax.inject.Inject;
|
||||
|
||||
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
AddContactHook, RemoveContactHook {
|
||||
Client, AddContactHook, RemoveContactHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
"673ea091673561e28f70122f6a8ea8f4"
|
||||
+ "97c3624b86fa07f785bb15f09fb87b4b"));
|
||||
|
||||
private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final ClientHelper clientHelper;
|
||||
private final PrivateGroupFactory privateGroupFactory;
|
||||
@@ -50,20 +47,28 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
|
||||
@Inject
|
||||
TransportPropertyManagerImpl(DatabaseComponent db,
|
||||
ClientHelper clientHelper, GroupFactory groupFactory,
|
||||
PrivateGroupFactory privateGroupFactory, Clock clock) {
|
||||
ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
this.privateGroupFactory = privateGroupFactory;
|
||||
this.clock = clock;
|
||||
localGroup = groupFactory.createGroup(CLIENT_ID,
|
||||
LOCAL_GROUP_DESCRIPTOR);
|
||||
localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLocalState(Transaction txn) throws DbException {
|
||||
db.addGroup(txn, localGroup);
|
||||
// Ensure we've set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
// Return if we've already set things up for this contact
|
||||
if (db.containsGroup(txn, g.getId())) return;
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setVisibleToContact(txn, c.getId(), g.getId(), true);
|
||||
@@ -126,9 +131,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return p;
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Local group doesn't exist - there are no local properties
|
||||
return null;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -169,8 +171,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// Create the local group if necessary
|
||||
db.addGroup(txn, localGroup);
|
||||
// Merge the new properties with any existing properties
|
||||
TransportProperties merged;
|
||||
boolean changed;
|
||||
@@ -230,9 +230,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
local.put(e.getKey(), parseProperties(message));
|
||||
}
|
||||
return local;
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Local group doesn't exist - there are no local properties
|
||||
return Collections.emptyMap();
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SyncModule {
|
||||
@Singleton
|
||||
ValidationManager getValidationManager(LifecycleManager lifecycleManager,
|
||||
EventBus eventBus, ValidationManagerImpl validationManager) {
|
||||
lifecycleManager.register(validationManager);
|
||||
lifecycleManager.registerService(validationManager);
|
||||
eventBus.addListener(validationManager);
|
||||
return validationManager;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class TransportModule {
|
||||
@Singleton
|
||||
KeyManager getKeyManager(LifecycleManager lifecycleManager,
|
||||
EventBus eventBus, KeyManagerImpl keyManager) {
|
||||
lifecycleManager.register(keyManager);
|
||||
lifecycleManager.registerService(keyManager);
|
||||
eventBus.addListener(keyManager);
|
||||
return keyManager;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject;
|
||||
|
||||
import org.briarproject.api.clients.Client;
|
||||
import org.briarproject.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
@@ -20,8 +21,14 @@ public class TestLifecycleModule {
|
||||
@Provides
|
||||
LifecycleManager provideLifecycleManager() {
|
||||
return new LifecycleManager() {
|
||||
|
||||
@Override
|
||||
public void register(Service s) {
|
||||
public void registerService(Service s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerClient(Client c) {
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +67,7 @@ public class TestLifecycleModule {
|
||||
@Provides
|
||||
ShutdownManager provideShutdownManager() {
|
||||
return new ShutdownManager() {
|
||||
|
||||
@Override
|
||||
public int addShutdownHook(Runnable hook) {
|
||||
return 0;
|
||||
@@ -75,8 +83,7 @@ public class TestLifecycleModule {
|
||||
@Provides
|
||||
@IoExecutor
|
||||
@Singleton
|
||||
Executor provideExecutor() {
|
||||
Executor provideIoExecutor() {
|
||||
return Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user