Commit 1bc29fec authored by Torsten Grote's avatar Torsten Grote

IntroductionManager and Protocol Engines

parent 61b216f5
package org.briarproject.briar.api.introduction2;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.messaging.ConversationManager.ConversationClient;
import java.util.Collection;
import javax.annotation.Nullable;
@NotNullByDefault
public interface IntroductionManager extends ConversationClient {
/**
* The unique ID of the introduction client.
*/
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.introduction");
/**
* The current version of the introduction client.
*/
int CLIENT_VERSION = 1;
/**
* Sends two initial introduction messages.
*/
void makeIntroduction(Contact c1, Contact c2, @Nullable String msg,
long timestamp) throws DbException;
/**
* Accepts an introduction.
*/
void acceptIntroduction(ContactId contactId, SessionId sessionId,
long timestamp) throws DbException;
/**
* Declines an introduction.
*/
void declineIntroduction(ContactId contactId, SessionId sessionId,
long timestamp) throws DbException;
/**
* Returns all introduction messages for the given contact.
*/
Collection<IntroductionMessage> getIntroductionMessages(ContactId contactId)
throws DbException;
}
......@@ -40,6 +40,7 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook,
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if a FormatException is thrown, the message will be permanently
......
package org.briarproject.briar.introduction2;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.briar.api.introduction2.IntroductionManager.CLIENT_ID;
import static org.briarproject.briar.api.introduction2.IntroductionManager.CLIENT_VERSION;
import static org.briarproject.briar.introduction2.MessageType.ABORT;
import static org.briarproject.briar.introduction2.MessageType.ACCEPT;
import static org.briarproject.briar.introduction2.MessageType.ACTIVATE;
import static org.briarproject.briar.introduction2.MessageType.AUTH;
import static org.briarproject.briar.introduction2.MessageType.DECLINE;
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
@Immutable
@NotNullByDefault
abstract class AbstractProtocolEngine<S extends Session>
implements ProtocolEngine<S> {
protected final DatabaseComponent db;
protected final ClientHelper clientHelper;
protected final ContactManager contactManager;
protected final ContactGroupFactory contactGroupFactory;
protected final MessageTracker messageTracker;
protected final IdentityManager identityManager;
protected final MessageParser messageParser;
protected final MessageEncoder messageEncoder;
protected final Clock clock;
AbstractProtocolEngine(
DatabaseComponent db,
ClientHelper clientHelper,
ContactManager contactManager,
ContactGroupFactory contactGroupFactory,
MessageTracker messageTracker,
IdentityManager identityManager,
MessageParser messageParser,
MessageEncoder messageEncoder,
Clock clock) {
this.db = db;
this.clientHelper = clientHelper;
this.contactManager = contactManager;
this.contactGroupFactory = contactGroupFactory;
this.messageTracker = messageTracker;
this.identityManager = identityManager;
this.messageParser = messageParser;
this.messageEncoder = messageEncoder;
this.clock = clock;
}
Message sendRequestMessage(Transaction txn, PeerSession s,
long timestamp, Author author, @Nullable String message)
throws DbException {
Message m = messageEncoder
.encodeRequestMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), author, message);
sendMessage(txn, REQUEST, s.getSessionId(), m, true);
return m;
}
Message sendAcceptMessage(Transaction txn, PeerSession s, long timestamp,
byte[] ephemeralPublicKey, long acceptTimestamp,
Map<TransportId, TransportProperties> transportProperties,
boolean visible)
throws DbException {
Message m = messageEncoder
.encodeAcceptMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), s.getSessionId(),
ephemeralPublicKey, acceptTimestamp,
transportProperties);
sendMessage(txn, ACCEPT, s.getSessionId(), m, visible);
return m;
}
Message sendDeclineMessage(Transaction txn, PeerSession s, long timestamp,
boolean visible) throws DbException {
Message m = messageEncoder
.encodeDeclineMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), s.getSessionId());
sendMessage(txn, DECLINE, s.getSessionId(), m, visible);
return m;
}
Message sendAuthMessage(Transaction txn, PeerSession s, long timestamp,
byte[] mac, byte[] signature) throws DbException {
Message m = messageEncoder
.encodeAuthMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), s.getSessionId(), mac,
signature);
sendMessage(txn, AUTH, s.getSessionId(), m, false);
return m;
}
Message sendActivateMessage(Transaction txn, PeerSession s, long timestamp)
throws DbException {
Message m = messageEncoder
.encodeActivateMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), s.getSessionId());
sendMessage(txn, ACTIVATE, s.getSessionId(), m, false);
return m;
}
Message sendAbortMessage(Transaction txn, PeerSession s, long timestamp)
throws DbException {
Message m = messageEncoder
.encodeAbortMessage(s.getContactGroupId(), timestamp,
s.getLastLocalMessageId(), s.getSessionId());
sendMessage(txn, ABORT, s.getSessionId(), m, false);
return m;
}
private void sendMessage(Transaction txn, MessageType type,
SessionId sessionId, Message m, boolean visibleInConversation)
throws DbException {
BdfDictionary meta = messageEncoder
.encodeMetadata(type, sessionId, m.getTimestamp(), true, true,
visibleInConversation);
try {
clientHelper.addLocalMessage(txn, m, meta, true);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
void markMessageVisibleInUi(Transaction txn, MessageId m)
throws DbException {
BdfDictionary meta = new BdfDictionary();
messageEncoder.setVisibleInUi(meta, true);
try {
clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
void markRequestUnavailableToAnswer(Transaction txn, MessageId m)
throws DbException {
BdfDictionary meta = new BdfDictionary();
messageEncoder.setAvailableToAnswer(meta, false);
try {
clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
Map<MessageId, BdfDictionary> getSessions(Transaction txn,
BdfDictionary query) throws DbException, FormatException {
return clientHelper
.getMessageMetadataAsDictionary(txn, getLocalGroup().getId(),
query);
}
private Group getLocalGroup() {
return contactGroupFactory.createLocalGroup(CLIENT_ID, CLIENT_VERSION);
}
boolean isInvalidDependency(@Nullable MessageId lastRemoteMessageId,
@Nullable MessageId dependency) {
if (dependency == null) return lastRemoteMessageId != null;
return lastRemoteMessageId == null ||
!dependency.equals(lastRemoteMessageId);
}
long getLocalTimestamp(long localTimestamp, long requestTimestamp) {
return Math.max(
clock.currentTimeMillis(),
Math.max(
localTimestamp,
requestTimestamp
) + 1
);
}
}
......@@ -2,6 +2,9 @@ package org.briarproject.briar.introduction2;
interface IntroductionConstants {
// Group metadata keys
String GROUP_KEY_CONTACT_ID = "contactId";
// Message metadata keys
String MSG_KEY_MESSAGE_TYPE = "messageType";
String MSG_KEY_SESSION_ID = "sessionId";
......
package org.briarproject.briar.introduction2;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
interface ProtocolEngine<S extends Session> {
S onRequestAction(Transaction txn, S session, @Nullable String message,
long timestamp) throws DbException;
S onAcceptAction(Transaction txn, S session, long timestamp)
throws DbException;
S onDeclineAction(Transaction txn, S session, long timestamp)
throws DbException;
S onRequestMessage(Transaction txn, S session, RequestMessage m)
throws DbException, FormatException;
S onAcceptMessage(Transaction txn, S session, AcceptMessage m)
throws DbException, FormatException;
S onDeclineMessage(Transaction txn, S session, DeclineMessage m)
throws DbException, FormatException;
S onAuthMessage(Transaction txn, S session, AuthMessage m)
throws DbException, FormatException;
S onActivateMessage(Transaction txn, S session, ActivateMessage m)
throws DbException, FormatException;
S onAbortMessage(Transaction txn, S session, AbortMessage m)
throws DbException, FormatException;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment