mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Find correct session state in case the same one is used twice.
The code made the assumption that a session state can be identified by the unique session ID. However, when multiple identities from the same device are involved, there are two sessions with the same ID running on the device. Hence, a second identifying criteria has to be used to uniquely identify the correct session. Here, the ID of the group was chosen. Unfortunately, the session state can not be cached easily anymore leading to a small performance penalty when getting all messages for the UI.
This commit is contained in:
@@ -663,9 +663,9 @@ public class ConversationActivity extends BriarActivity
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
if (accept) {
|
if (accept) {
|
||||||
introductionManager.acceptIntroduction(sessionId);
|
introductionManager.acceptIntroduction(contactId, sessionId);
|
||||||
} else {
|
} else {
|
||||||
introductionManager.declineIntroduction(sessionId);
|
introductionManager.declineIntroduction(contactId, sessionId);
|
||||||
}
|
}
|
||||||
loadMessages();
|
loadMessages();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.briarproject.api.db.DbException;
|
|||||||
import org.briarproject.api.db.Transaction;
|
import org.briarproject.api.db.Transaction;
|
||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
import org.briarproject.api.sync.Group;
|
import org.briarproject.api.sync.Group;
|
||||||
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -26,14 +27,14 @@ public interface IntroductionManager {
|
|||||||
/**
|
/**
|
||||||
* Accept an introduction that had been made
|
* Accept an introduction that had been made
|
||||||
*/
|
*/
|
||||||
void acceptIntroduction(final SessionId sessionId)
|
void acceptIntroduction(final ContactId contactId,
|
||||||
throws DbException, FormatException;
|
final SessionId sessionId) throws DbException, FormatException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decline an introduction that had been made
|
* Decline an introduction that had been made
|
||||||
*/
|
*/
|
||||||
void declineIntroduction(final SessionId sessionId)
|
void declineIntroduction(final ContactId contactId,
|
||||||
throws DbException, FormatException;
|
final SessionId sessionId) throws DbException, FormatException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all introduction messages for the contact with this contactId
|
* Get all introduction messages for the contact with this contactId
|
||||||
@@ -46,8 +47,8 @@ public interface IntroductionManager {
|
|||||||
|
|
||||||
|
|
||||||
/** Get the session state for the given session ID */
|
/** Get the session state for the given session ID */
|
||||||
BdfDictionary getSessionState(Transaction txn, byte[] sessionId)
|
BdfDictionary getSessionState(Transaction txn, GroupId groupId,
|
||||||
throws DbException, FormatException;
|
byte[] sessionId) throws DbException, FormatException;
|
||||||
|
|
||||||
/** Gets the group used for introductions with Contact c */
|
/** Gets the group used for introductions with Contact c */
|
||||||
Group getIntroductionGroup(Contact c);
|
Group getIntroductionGroup(Contact c);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.briarproject.api.introduction.IntroductionManager;
|
|||||||
import org.briarproject.api.introduction.SessionId;
|
import org.briarproject.api.introduction.SessionId;
|
||||||
import org.briarproject.api.properties.TransportProperties;
|
import org.briarproject.api.properties.TransportProperties;
|
||||||
import org.briarproject.api.properties.TransportPropertyManager;
|
import org.briarproject.api.properties.TransportPropertyManager;
|
||||||
|
import org.briarproject.api.sync.Group;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.Message;
|
import org.briarproject.api.sync.Message;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
@@ -157,11 +158,14 @@ class IntroduceeManager {
|
|||||||
processStateUpdate(txn, engine.onMessageReceived(state, message));
|
processStateUpdate(txn, engine.onMessageReceived(state, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void acceptIntroduction(Transaction txn,
|
public void acceptIntroduction(Transaction txn, final ContactId contactId,
|
||||||
final SessionId sessionId) throws DbException, FormatException {
|
final SessionId sessionId) throws DbException, FormatException {
|
||||||
|
|
||||||
BdfDictionary state =
|
Contact c = contactManager.getContact(contactId);
|
||||||
introductionManager.getSessionState(txn, sessionId.getBytes());
|
Group g = introductionManager.getIntroductionGroup(c);
|
||||||
|
|
||||||
|
BdfDictionary state = introductionManager
|
||||||
|
.getSessionState(txn, g.getId(), sessionId.getBytes());
|
||||||
|
|
||||||
// get data to connect and derive a shared secret later
|
// get data to connect and derive a shared secret later
|
||||||
long now = clock.currentTimeMillis();
|
long now = clock.currentTimeMillis();
|
||||||
@@ -188,11 +192,14 @@ class IntroduceeManager {
|
|||||||
processStateUpdate(txn, engine.onLocalAction(state, localAction));
|
processStateUpdate(txn, engine.onLocalAction(state, localAction));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void declineIntroduction(Transaction txn, final SessionId sessionId)
|
public void declineIntroduction(Transaction txn, final ContactId contactId,
|
||||||
throws DbException, FormatException {
|
final SessionId sessionId) throws DbException, FormatException {
|
||||||
|
|
||||||
BdfDictionary state =
|
Contact c = contactManager.getContact(contactId);
|
||||||
introductionManager.getSessionState(txn, sessionId.getBytes());
|
Group g = introductionManager.getIntroductionGroup(c);
|
||||||
|
|
||||||
|
BdfDictionary state = introductionManager
|
||||||
|
.getSessionState(txn, g.getId(), sessionId.getBytes());
|
||||||
|
|
||||||
// update session state
|
// update session state
|
||||||
state.put(ACCEPT, false);
|
state.put(ACCEPT, false);
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID
|
|||||||
import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
|
import static org.briarproject.api.introduction.IntroductionConstants.CONTACT_ID_2;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
|
import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
|
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
|
||||||
|
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_1;
|
||||||
|
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID_2;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
|
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
|
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
|
||||||
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
|
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
|
||||||
@@ -227,7 +229,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
else if (type == TYPE_RESPONSE || type == TYPE_ACK || type == TYPE_ABORT) {
|
else if (type == TYPE_RESPONSE || type == TYPE_ACK || type == TYPE_ABORT) {
|
||||||
BdfDictionary state;
|
BdfDictionary state;
|
||||||
try {
|
try {
|
||||||
state = getSessionState(txn,
|
state = getSessionState(txn, groupId,
|
||||||
message.getRaw(SESSION_ID, new byte[0]));
|
message.getRaw(SESSION_ID, new byte[0]));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
LOG.warning("Could not find state for message, deleting...");
|
LOG.warning("Could not find state for message, deleting...");
|
||||||
@@ -279,12 +281,12 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptIntroduction(final SessionId sessionId)
|
public void acceptIntroduction(final ContactId contactId,
|
||||||
throws DbException, FormatException {
|
final SessionId sessionId) throws DbException, FormatException {
|
||||||
|
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
introduceeManager.acceptIntroduction(txn, sessionId);
|
introduceeManager.acceptIntroduction(txn, contactId, sessionId);
|
||||||
txn.setComplete();
|
txn.setComplete();
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
@@ -292,12 +294,12 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void declineIntroduction(final SessionId sessionId)
|
public void declineIntroduction(final ContactId contactId,
|
||||||
throws DbException, FormatException {
|
final SessionId sessionId) throws DbException, FormatException {
|
||||||
|
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
introduceeManager.declineIntroduction(txn, sessionId);
|
introduceeManager.declineIntroduction(txn, contactId, sessionId);
|
||||||
txn.setComplete();
|
txn.setComplete();
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
@@ -322,8 +324,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
statuses = db.getMessageStatus(txn, contactId, g);
|
statuses = db.getMessageStatus(txn, contactId, g);
|
||||||
|
|
||||||
// turn messages into classes for the UI
|
// turn messages into classes for the UI
|
||||||
Map<SessionId, BdfDictionary> sessionStates =
|
|
||||||
new HashMap<SessionId, BdfDictionary>();
|
|
||||||
for (MessageStatus s : statuses) {
|
for (MessageStatus s : statuses) {
|
||||||
MessageId messageId = s.getMessageId();
|
MessageId messageId = s.getMessageId();
|
||||||
BdfDictionary msg = metadata.get(messageId);
|
BdfDictionary msg = metadata.get(messageId);
|
||||||
@@ -335,11 +335,8 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
|
|
||||||
// get session state
|
// get session state
|
||||||
SessionId sessionId = new SessionId(msg.getRaw(SESSION_ID));
|
SessionId sessionId = new SessionId(msg.getRaw(SESSION_ID));
|
||||||
BdfDictionary state = sessionStates.get(sessionId);
|
BdfDictionary state =
|
||||||
if (state == null) {
|
getSessionState(txn, g, sessionId.getBytes());
|
||||||
state = getSessionState(txn, sessionId.getBytes());
|
|
||||||
}
|
|
||||||
sessionStates.put(sessionId, state);
|
|
||||||
|
|
||||||
boolean local;
|
boolean local;
|
||||||
long time = msg.getLong(MESSAGE_TIME);
|
long time = msg.getLong(MESSAGE_TIME);
|
||||||
@@ -453,19 +450,31 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getSessionState(Transaction txn, byte[] sessionId)
|
public BdfDictionary getSessionState(Transaction txn, GroupId groupId,
|
||||||
throws DbException, FormatException {
|
byte[] sessionId) throws DbException, FormatException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return clientHelper.getMessageMetadataAsDictionary(txn,
|
// See if we can find the state directly for the introducer
|
||||||
new MessageId(sessionId));
|
BdfDictionary state = clientHelper
|
||||||
|
.getMessageMetadataAsDictionary(txn,
|
||||||
|
new MessageId(sessionId));
|
||||||
|
GroupId g1 = new GroupId(state.getRaw(GROUP_ID_1));
|
||||||
|
GroupId g2 = new GroupId(state.getRaw(GROUP_ID_2));
|
||||||
|
if (!g1.equals(groupId) && !g2.equals(groupId)) {
|
||||||
|
throw new NoSuchMessageException();
|
||||||
|
}
|
||||||
|
return state;
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
|
// State not found directly, so iterate over all states
|
||||||
|
// to find state for introducee
|
||||||
Map<MessageId, BdfDictionary> map = clientHelper
|
Map<MessageId, BdfDictionary> map = clientHelper
|
||||||
.getMessageMetadataAsDictionary(txn,
|
.getMessageMetadataAsDictionary(txn,
|
||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
|
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
|
||||||
if (Arrays.equals(m.getValue().getRaw(SESSION_ID), sessionId)) {
|
if (Arrays.equals(m.getValue().getRaw(SESSION_ID), sessionId)) {
|
||||||
return m.getValue();
|
BdfDictionary state = m.getValue();
|
||||||
|
GroupId g = new GroupId(state.getRaw(GROUP_ID));
|
||||||
|
if (g.equals(groupId)) return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isLoggable(WARNING)) {
|
if (LOG.isLoggable(WARNING)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user