mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Turn local session state into its own class instead of BdfDictionary
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
package org.briarproject.api.forum;
|
||||
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
|
||||
public enum InviteeAction {
|
||||
|
||||
LOCAL_ACCEPT,
|
||||
LOCAL_DECLINE,
|
||||
LOCAL_LEAVE,
|
||||
LOCAL_ABORT,
|
||||
REMOTE_INVITATION,
|
||||
REMOTE_LEAVE,
|
||||
REMOTE_ABORT;
|
||||
|
||||
public static InviteeAction getLocal(long type) {
|
||||
if (type == SHARE_MSG_TYPE_ACCEPT) return LOCAL_ACCEPT;
|
||||
if (type == SHARE_MSG_TYPE_DECLINE) return LOCAL_DECLINE;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static InviteeAction getRemote(long type) {
|
||||
if (type == SHARE_MSG_TYPE_INVITATION) return REMOTE_INVITATION;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.briarproject.api.forum;
|
||||
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_ACCEPT;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_DECLINE;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_LEAVE;
|
||||
import static org.briarproject.api.forum.InviteeAction.REMOTE_INVITATION;
|
||||
import static org.briarproject.api.forum.InviteeAction.REMOTE_LEAVE;
|
||||
|
||||
public enum InviteeProtocolState {
|
||||
|
||||
ERROR(0),
|
||||
AWAIT_INVITATION(1) {
|
||||
@Override
|
||||
public InviteeProtocolState next(InviteeAction a) {
|
||||
if (a == REMOTE_INVITATION) return AWAIT_LOCAL_RESPONSE;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
AWAIT_LOCAL_RESPONSE(2) {
|
||||
@Override
|
||||
public InviteeProtocolState next(InviteeAction a) {
|
||||
if (a == LOCAL_ACCEPT || a == LOCAL_DECLINE) return FINISHED;
|
||||
if (a == REMOTE_LEAVE) return LEFT;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
FINISHED(3) {
|
||||
@Override
|
||||
public InviteeProtocolState next(InviteeAction a) {
|
||||
if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
|
||||
return FINISHED;
|
||||
}
|
||||
},
|
||||
LEFT(4) {
|
||||
@Override
|
||||
public InviteeProtocolState next(InviteeAction a) {
|
||||
if (a == LOCAL_LEAVE) return ERROR;
|
||||
return LEFT;
|
||||
}
|
||||
};
|
||||
|
||||
private final int value;
|
||||
|
||||
InviteeProtocolState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static InviteeProtocolState fromValue(int value) {
|
||||
for (InviteeProtocolState s : values()) {
|
||||
if (s.value == value) return s;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public InviteeProtocolState next(InviteeAction a) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.briarproject.api.forum;
|
||||
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
|
||||
public enum SharerAction {
|
||||
|
||||
LOCAL_INVITATION,
|
||||
LOCAL_LEAVE,
|
||||
LOCAL_ABORT,
|
||||
REMOTE_ACCEPT,
|
||||
REMOTE_DECLINE,
|
||||
REMOTE_LEAVE,
|
||||
REMOTE_ABORT;
|
||||
|
||||
public static SharerAction getLocal(long type) {
|
||||
if (type == SHARE_MSG_TYPE_INVITATION) return LOCAL_INVITATION;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SharerAction getRemote(long type) {
|
||||
if (type == SHARE_MSG_TYPE_ACCEPT) return REMOTE_ACCEPT;
|
||||
if (type == SHARE_MSG_TYPE_DECLINE) return REMOTE_DECLINE;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.briarproject.api.forum;
|
||||
|
||||
import static org.briarproject.api.forum.SharerAction.LOCAL_INVITATION;
|
||||
import static org.briarproject.api.forum.SharerAction.LOCAL_LEAVE;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_ACCEPT;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_DECLINE;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_LEAVE;
|
||||
|
||||
public enum SharerProtocolState {
|
||||
|
||||
ERROR(0),
|
||||
PREPARE_INVITATION(1) {
|
||||
@Override
|
||||
public SharerProtocolState next(SharerAction a) {
|
||||
if (a == LOCAL_INVITATION) return AWAIT_RESPONSE;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
AWAIT_RESPONSE(2) {
|
||||
@Override
|
||||
public SharerProtocolState next(SharerAction a) {
|
||||
if (a == REMOTE_ACCEPT || a == REMOTE_DECLINE) return FINISHED;
|
||||
if (a == LOCAL_LEAVE) return LEFT;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
FINISHED(3) {
|
||||
@Override
|
||||
public SharerProtocolState next(SharerAction a) {
|
||||
if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
|
||||
return FINISHED;
|
||||
}
|
||||
},
|
||||
LEFT(4) {
|
||||
@Override
|
||||
public SharerProtocolState next(SharerAction a) {
|
||||
if (a == LOCAL_LEAVE) return ERROR;
|
||||
return LEFT;
|
||||
}
|
||||
};
|
||||
|
||||
private final int value;
|
||||
|
||||
SharerProtocolState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static SharerProtocolState fromValue(int value) {
|
||||
for (SharerProtocolState s : values()) {
|
||||
if (s.value == value) return s;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public SharerProtocolState next(SharerAction a) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,6 @@ import org.briarproject.api.forum.ForumFactory;
|
||||
import org.briarproject.api.forum.ForumInvitationMessage;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumSharingManager;
|
||||
import org.briarproject.api.forum.InviteeAction;
|
||||
import org.briarproject.api.forum.InviteeProtocolState;
|
||||
import org.briarproject.api.forum.SharerAction;
|
||||
import org.briarproject.api.forum.SharerProtocolState;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
@@ -59,7 +55,6 @@ import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
|
||||
import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
|
||||
@@ -76,11 +71,8 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STORAGE_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US;
|
||||
@@ -91,9 +83,8 @@ import static org.briarproject.api.forum.ForumConstants.TIME;
|
||||
import static org.briarproject.api.forum.ForumConstants.TO_BE_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TYPE;
|
||||
import static org.briarproject.api.forum.ForumManager.RemoveForumHook;
|
||||
import static org.briarproject.api.forum.InviteeProtocolState.AWAIT_INVITATION;
|
||||
import static org.briarproject.api.forum.InviteeProtocolState.AWAIT_LOCAL_RESPONSE;
|
||||
import static org.briarproject.api.forum.SharerProtocolState.PREPARE_INVITATION;
|
||||
import static org.briarproject.forum.ForumSharingSessionState.fromBdfDictionary;
|
||||
import static org.briarproject.forum.SharerSessionState.Action;
|
||||
|
||||
class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
implements ForumSharingManager, Client, RemoveForumHook,
|
||||
@@ -214,10 +205,10 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
throw new FormatException();
|
||||
|
||||
// initialize state and process invitation
|
||||
BdfDictionary state =
|
||||
InviteeSessionState state =
|
||||
initializeInviteeState(txn, contactId, msg);
|
||||
InviteeEngine engine = new InviteeEngine(forumFactory);
|
||||
processStateUpdate(txn, m.getId(),
|
||||
processInviteeStateUpdate(txn, m.getId(),
|
||||
engine.onMessageReceived(state, msg));
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -226,23 +217,25 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
} else if (type == SHARE_MSG_TYPE_ACCEPT ||
|
||||
type == SHARE_MSG_TYPE_DECLINE) {
|
||||
// we are a sharer who just received a response
|
||||
BdfDictionary state = getSessionState(txn, sessionId, true);
|
||||
SharerSessionState state = getSessionStateForSharer(txn, sessionId);
|
||||
SharerEngine engine = new SharerEngine();
|
||||
processStateUpdate(txn, m.getId(),
|
||||
processSharerStateUpdate(txn, m.getId(),
|
||||
engine.onMessageReceived(state, msg));
|
||||
} else if (type == SHARE_MSG_TYPE_LEAVE ||
|
||||
type == SHARE_MSG_TYPE_ABORT) {
|
||||
// we don't know who we are, so figure it out
|
||||
BdfDictionary state = getSessionState(txn, sessionId, true);
|
||||
if (state.getBoolean(IS_SHARER)) {
|
||||
ForumSharingSessionState s = getSessionState(txn, sessionId, true);
|
||||
if (s instanceof SharerSessionState) {
|
||||
// we are a sharer and the invitee wants to leave or abort
|
||||
SharerSessionState state = (SharerSessionState) s;
|
||||
SharerEngine engine = new SharerEngine();
|
||||
processStateUpdate(txn, m.getId(),
|
||||
processSharerStateUpdate(txn, m.getId(),
|
||||
engine.onMessageReceived(state, msg));
|
||||
} else {
|
||||
// we are an invitee and the sharer wants to leave or abort
|
||||
InviteeSessionState state = (InviteeSessionState) s;
|
||||
InviteeEngine engine = new InviteeEngine(forumFactory);
|
||||
processStateUpdate(txn, m.getId(),
|
||||
processInviteeStateUpdate(txn, m.getId(),
|
||||
engine.onMessageReceived(state, msg));
|
||||
}
|
||||
} else {
|
||||
@@ -264,7 +257,8 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
try {
|
||||
// initialize local state for sharer
|
||||
Forum f = forumManager.getForum(txn, groupId);
|
||||
BdfDictionary localState = initializeSharerState(txn, f, contactId);
|
||||
SharerSessionState localState =
|
||||
initializeSharerState(txn, f, contactId);
|
||||
|
||||
// define action
|
||||
BdfDictionary localAction = new BdfDictionary();
|
||||
@@ -275,7 +269,7 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
|
||||
// start engine and process its state update
|
||||
SharerEngine engine = new SharerEngine();
|
||||
processStateUpdate(txn, null,
|
||||
processSharerStateUpdate(txn, null,
|
||||
engine.onLocalAction(localState, localAction));
|
||||
|
||||
txn.setComplete();
|
||||
@@ -293,7 +287,7 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// find session state based on forum
|
||||
BdfDictionary localState = getSessionStateForResponse(txn, f);
|
||||
InviteeSessionState localState = getSessionStateForResponse(txn, f);
|
||||
|
||||
// define action
|
||||
BdfDictionary localAction = new BdfDictionary();
|
||||
@@ -305,7 +299,7 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
|
||||
// start engine and process its state update
|
||||
InviteeEngine engine = new InviteeEngine(forumFactory);
|
||||
processStateUpdate(txn, null,
|
||||
processInviteeStateUpdate(txn, null,
|
||||
engine.onLocalAction(localState, localAction));
|
||||
|
||||
txn.setComplete();
|
||||
@@ -346,12 +340,12 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
boolean available = false;
|
||||
if (!local) {
|
||||
// figure out whether the forum is still available
|
||||
BdfDictionary sessionState =
|
||||
ForumSharingSessionState s =
|
||||
getSessionState(txn, sessionId, true);
|
||||
InviteeProtocolState state = InviteeProtocolState
|
||||
.fromValue(
|
||||
sessionState.getLong(STATE).intValue());
|
||||
available = state == AWAIT_LOCAL_RESPONSE;
|
||||
if (!(s instanceof InviteeSessionState))
|
||||
continue;
|
||||
available = ((InviteeSessionState) s).getState() ==
|
||||
InviteeSessionState.State.AWAIT_LOCAL_RESPONSE;
|
||||
}
|
||||
ForumInvitationMessage im =
|
||||
new ForumInvitationMessage(m.getKey(), sessionId,
|
||||
@@ -490,7 +484,7 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
}
|
||||
}
|
||||
|
||||
private BdfDictionary initializeSharerState(Transaction txn, Forum f,
|
||||
private SharerSessionState initializeSharerState(Transaction txn, Forum f,
|
||||
ContactId contactId) throws FormatException, DbException {
|
||||
|
||||
Contact c = db.getContact(txn, contactId);
|
||||
@@ -502,26 +496,20 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
random.nextBytes(salt.getBytes());
|
||||
Message m = clientHelper.createMessage(localGroup.getId(), now,
|
||||
BdfList.of(salt));
|
||||
MessageId sessionId = m.getId();
|
||||
SessionId sessionId = new SessionId(m.getId().getBytes());
|
||||
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put(SESSION_ID, sessionId);
|
||||
d.put(STORAGE_ID, sessionId);
|
||||
d.put(GROUP_ID, group.getId());
|
||||
d.put(IS_SHARER, true);
|
||||
d.put(STATE, PREPARE_INVITATION.getValue());
|
||||
d.put(CONTACT_ID, contactId.getInt());
|
||||
d.put(FORUM_ID, f.getId());
|
||||
d.put(FORUM_NAME, f.getName());
|
||||
d.put(FORUM_SALT, f.getSalt());
|
||||
SharerSessionState s = new SharerSessionState(sessionId, sessionId,
|
||||
group.getId(), SharerSessionState.State.PREPARE_INVITATION,
|
||||
contactId, f.getId(), f.getName(), f.getSalt());
|
||||
|
||||
// save local state to database
|
||||
BdfDictionary d = s.toBdfDictionary();
|
||||
clientHelper.addLocalMessage(txn, m, getClientId(), d, false);
|
||||
|
||||
return d;
|
||||
return s;
|
||||
}
|
||||
|
||||
private BdfDictionary initializeInviteeState(Transaction txn,
|
||||
private InviteeSessionState initializeInviteeState(Transaction txn,
|
||||
ContactId contactId, BdfDictionary msg)
|
||||
throws FormatException, DbException {
|
||||
|
||||
@@ -538,29 +526,25 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
Message m = clientHelper.createMessage(localGroup.getId(), now,
|
||||
BdfList.of(mSalt));
|
||||
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put(SESSION_ID, msg.getRaw(SESSION_ID));
|
||||
d.put(STORAGE_ID, m.getId());
|
||||
d.put(GROUP_ID, group.getId());
|
||||
d.put(IS_SHARER, false);
|
||||
d.put(STATE, AWAIT_INVITATION.getValue());
|
||||
d.put(CONTACT_ID, contactId.getInt());
|
||||
d.put(FORUM_ID, f.getId());
|
||||
d.put(FORUM_NAME, name);
|
||||
d.put(FORUM_SALT, salt);
|
||||
SessionId sessionId = new SessionId(msg.getRaw(SESSION_ID));
|
||||
|
||||
InviteeSessionState s = new InviteeSessionState(sessionId, m.getId(),
|
||||
group.getId(), InviteeSessionState.State.AWAIT_INVITATION,
|
||||
contactId, f.getId(), f.getName(), f.getSalt());
|
||||
|
||||
// save local state to database
|
||||
BdfDictionary d = s.toBdfDictionary();
|
||||
clientHelper.addLocalMessage(txn, m, getClientId(), d, false);
|
||||
|
||||
return d;
|
||||
return s;
|
||||
}
|
||||
|
||||
private BdfDictionary getSessionState(Transaction txn, SessionId sessionId,
|
||||
boolean warn) throws DbException, FormatException {
|
||||
private ForumSharingSessionState getSessionState(Transaction txn,
|
||||
SessionId sessionId, boolean warn)
|
||||
throws DbException, FormatException {
|
||||
|
||||
try {
|
||||
// we should be able to get the sharer state directly from sessionId
|
||||
return clientHelper.getMessageMetadataAsDictionary(txn, sessionId);
|
||||
return getSessionStateForSharer(txn, sessionId);
|
||||
} catch (NoSuchMessageException e) {
|
||||
// State not found directly, so iterate over all states
|
||||
// to find state for invitee
|
||||
@@ -570,7 +554,7 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
BdfDictionary state = m.getValue();
|
||||
if (Arrays.equals(state.getRaw(SESSION_ID),
|
||||
sessionId.getBytes())) {
|
||||
return state;
|
||||
return fromBdfDictionary(state);
|
||||
}
|
||||
}
|
||||
if (warn && LOG.isLoggable(WARNING)) {
|
||||
@@ -582,23 +566,37 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
}
|
||||
}
|
||||
|
||||
private BdfDictionary getSessionStateForResponse(Transaction txn, Forum f)
|
||||
private SharerSessionState getSessionStateForSharer(Transaction txn,
|
||||
SessionId sessionId)
|
||||
throws DbException, FormatException {
|
||||
|
||||
// we should be able to get the sharer state directly from sessionId
|
||||
BdfDictionary d =
|
||||
clientHelper.getMessageMetadataAsDictionary(txn, sessionId);
|
||||
|
||||
if (!d.getBoolean(IS_SHARER)) throw new FormatException();
|
||||
|
||||
return (SharerSessionState) fromBdfDictionary(d);
|
||||
}
|
||||
|
||||
private InviteeSessionState getSessionStateForResponse(Transaction txn,
|
||||
Forum f) throws DbException, FormatException {
|
||||
|
||||
Map<MessageId, BdfDictionary> map = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, localGroup.getId());
|
||||
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
|
||||
BdfDictionary d = m.getValue();
|
||||
try {
|
||||
InviteeProtocolState state = InviteeProtocolState
|
||||
.fromValue(d.getLong(STATE).intValue());
|
||||
if (state == AWAIT_LOCAL_RESPONSE) {
|
||||
byte[] id = d.getRaw(FORUM_ID);
|
||||
if (Arrays.equals(f.getId().getBytes(), id)) {
|
||||
// Note that there should always be only one session
|
||||
// in this state for the same forum
|
||||
return d;
|
||||
}
|
||||
ForumSharingSessionState s = fromBdfDictionary(d);
|
||||
if (!(s instanceof InviteeSessionState)) continue;
|
||||
if (!f.getId().equals(s.getForumId())) continue;
|
||||
|
||||
InviteeSessionState state = (InviteeSessionState) s;
|
||||
if (state.getState() ==
|
||||
InviteeSessionState.State.AWAIT_LOCAL_RESPONSE) {
|
||||
// Note that there should always be only one session
|
||||
// in this state for the same forum
|
||||
return state;
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -607,36 +605,40 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
throw new DbException();
|
||||
}
|
||||
|
||||
private BdfDictionary getSessionStateForLeaving(Transaction txn, Forum f,
|
||||
ContactId c) throws DbException, FormatException {
|
||||
private ForumSharingSessionState getSessionStateForLeaving(Transaction txn,
|
||||
Forum f, ContactId c) throws DbException, FormatException {
|
||||
|
||||
Map<MessageId, BdfDictionary> map = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, localGroup.getId());
|
||||
for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
|
||||
BdfDictionary d = m.getValue();
|
||||
try {
|
||||
ForumSharingSessionState s = fromBdfDictionary(d);
|
||||
|
||||
// check that this session is with the right contact
|
||||
if (c.getInt() != d.getLong(CONTACT_ID)) continue;
|
||||
// check that a forum get be left in current session
|
||||
int intState = d.getLong(STATE).intValue();
|
||||
if (d.getBoolean(IS_SHARER)) {
|
||||
SharerProtocolState state =
|
||||
SharerProtocolState.fromValue(intState);
|
||||
if (state.next(SharerAction.LOCAL_LEAVE) ==
|
||||
SharerProtocolState.ERROR) continue;
|
||||
} else {
|
||||
InviteeProtocolState state = InviteeProtocolState
|
||||
.fromValue(intState);
|
||||
if (state.next(InviteeAction.LOCAL_LEAVE) ==
|
||||
InviteeProtocolState.ERROR) continue;
|
||||
}
|
||||
if (!c.equals(s.getContactId())) continue;
|
||||
|
||||
// check that this state actually concerns this forum
|
||||
String name = d.getString(FORUM_NAME);
|
||||
byte[] salt = d.getRaw(FORUM_SALT);
|
||||
if (name.equals(f.getName()) &&
|
||||
Arrays.equals(salt, f.getSalt())) {
|
||||
// TODO what happens when there is more than one invitation?
|
||||
return d;
|
||||
if (!s.getForumName().equals(f.getName()) ||
|
||||
!Arrays.equals(s.getForumSalt(), f.getSalt())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check that a forum get be left in current session
|
||||
if (s instanceof SharerSessionState) {
|
||||
SharerSessionState state = (SharerSessionState) s;
|
||||
SharerSessionState.State nextState =
|
||||
state.getState().next(Action.LOCAL_LEAVE);
|
||||
if (nextState != SharerSessionState.State.ERROR) {
|
||||
return state;
|
||||
}
|
||||
} else {
|
||||
InviteeSessionState state = (InviteeSessionState) s;
|
||||
InviteeSessionState.State nextState = state.getState()
|
||||
.next(InviteeSessionState.Action.LOCAL_LEAVE);
|
||||
if (nextState != InviteeSessionState.State.ERROR) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
@@ -646,16 +648,16 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
}
|
||||
|
||||
private void processStateUpdate(Transaction txn, MessageId messageId,
|
||||
StateUpdate<BdfDictionary, BdfDictionary> result)
|
||||
StateUpdate<ForumSharingSessionState, BdfDictionary> result)
|
||||
throws DbException, FormatException {
|
||||
|
||||
// perform actions based on new local state
|
||||
performTasks(txn, result.localState);
|
||||
|
||||
// save new local state
|
||||
MessageId storageId =
|
||||
new MessageId(result.localState.getRaw(STORAGE_ID));
|
||||
clientHelper.mergeMessageMetadata(txn, storageId, result.localState);
|
||||
MessageId storageId = result.localState.getStorageId();
|
||||
clientHelper.mergeMessageMetadata(txn, storageId,
|
||||
result.localState.toBdfDictionary());
|
||||
|
||||
// send messages
|
||||
for (BdfDictionary d : result.toSend) {
|
||||
@@ -677,24 +679,47 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
}
|
||||
}
|
||||
|
||||
private void performTasks(Transaction txn, BdfDictionary localState)
|
||||
private void processSharerStateUpdate(Transaction txn, MessageId messageId,
|
||||
StateUpdate<SharerSessionState, BdfDictionary> result)
|
||||
throws DbException, FormatException {
|
||||
|
||||
StateUpdate<ForumSharingSessionState, BdfDictionary> r =
|
||||
new StateUpdate<ForumSharingSessionState, BdfDictionary>(
|
||||
result.deleteMessage, result.deleteState,
|
||||
result.localState, result.toSend, result.toBroadcast);
|
||||
|
||||
processStateUpdate(txn, messageId, r);
|
||||
}
|
||||
|
||||
private void processInviteeStateUpdate(Transaction txn, MessageId messageId,
|
||||
StateUpdate<InviteeSessionState, BdfDictionary> result)
|
||||
throws DbException, FormatException {
|
||||
|
||||
StateUpdate<ForumSharingSessionState, BdfDictionary> r =
|
||||
new StateUpdate<ForumSharingSessionState, BdfDictionary>(
|
||||
result.deleteMessage, result.deleteState,
|
||||
result.localState, result.toSend, result.toBroadcast);
|
||||
|
||||
processStateUpdate(txn, messageId, r);
|
||||
}
|
||||
|
||||
private void performTasks(Transaction txn, ForumSharingSessionState localState)
|
||||
throws FormatException, DbException {
|
||||
|
||||
if (!localState.containsKey(TASK)) return;
|
||||
if (localState.getTask() == -1) return;
|
||||
|
||||
// remember task and remove it from localState
|
||||
long task = localState.getLong(TASK);
|
||||
localState.put(TASK, BdfDictionary.NULL_VALUE);
|
||||
long task = localState.getTask();
|
||||
localState.setTask(-1);
|
||||
|
||||
// get group ID for later
|
||||
GroupId groupId = new GroupId(localState.getRaw(GROUP_ID));
|
||||
GroupId groupId = localState.getGroupId();
|
||||
// get contact ID for later
|
||||
ContactId contactId =
|
||||
new ContactId(localState.getLong(CONTACT_ID).intValue());
|
||||
ContactId contactId = localState.getContactId();
|
||||
|
||||
// get forum for later
|
||||
String name = localState.getString(FORUM_NAME);
|
||||
byte[] salt = localState.getRaw(FORUM_SALT);
|
||||
String name = localState.getForumName();
|
||||
byte[] salt = localState.getForumSalt();
|
||||
Forum f = forumFactory.createForum(name, salt);
|
||||
|
||||
// perform tasks
|
||||
@@ -786,17 +811,17 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
|
||||
private void leaveForum(Transaction txn, ContactId c, Forum f)
|
||||
throws DbException, FormatException {
|
||||
|
||||
BdfDictionary state = getSessionStateForLeaving(txn, f, c);
|
||||
ForumSharingSessionState state = getSessionStateForLeaving(txn, f, c);
|
||||
BdfDictionary action = new BdfDictionary();
|
||||
action.put(TYPE, SHARE_MSG_TYPE_LEAVE);
|
||||
if (state.getBoolean(IS_SHARER)) {
|
||||
if (state instanceof SharerSessionState) {
|
||||
SharerEngine engine = new SharerEngine();
|
||||
processStateUpdate(txn, null,
|
||||
engine.onLocalAction(state, action));
|
||||
processSharerStateUpdate(txn, null,
|
||||
engine.onLocalAction((SharerSessionState) state, action));
|
||||
} else {
|
||||
InviteeEngine engine = new InviteeEngine(forumFactory);
|
||||
processStateUpdate(txn, null,
|
||||
engine.onLocalAction(state, action));
|
||||
processInviteeStateUpdate(txn, null,
|
||||
engine.onLocalAction((InviteeSessionState) state, action));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.briarproject.forum;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
|
||||
import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
|
||||
import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STORAGE_ID;
|
||||
|
||||
// This class is not thread-safe
|
||||
public abstract class ForumSharingSessionState {
|
||||
|
||||
private final SessionId sessionId;
|
||||
private final MessageId storageId;
|
||||
private final GroupId groupId;
|
||||
private final ContactId contactId;
|
||||
private final GroupId forumId;
|
||||
private final String forumName;
|
||||
private final byte[] forumSalt;
|
||||
private int task = -1; // TODO get rid of task, see #376
|
||||
|
||||
public ForumSharingSessionState(SessionId sessionId, MessageId storageId,
|
||||
GroupId groupId, ContactId contactId, GroupId forumId,
|
||||
String forumName, byte[] forumSalt) {
|
||||
|
||||
this.sessionId = sessionId;
|
||||
this.storageId = storageId;
|
||||
this.groupId = groupId;
|
||||
this.contactId = contactId;
|
||||
this.forumId = forumId;
|
||||
this.forumName = forumName;
|
||||
this.forumSalt = forumSalt;
|
||||
}
|
||||
|
||||
public static ForumSharingSessionState fromBdfDictionary(BdfDictionary d)
|
||||
throws FormatException{
|
||||
|
||||
SessionId sessionId = new SessionId(d.getRaw(SESSION_ID));
|
||||
MessageId messageId = new MessageId(d.getRaw(STORAGE_ID));
|
||||
GroupId groupId = new GroupId(d.getRaw(GROUP_ID));
|
||||
ContactId contactId = new ContactId(d.getLong(CONTACT_ID).intValue());
|
||||
GroupId forumId = new GroupId(d.getRaw(FORUM_ID));
|
||||
String forumName = d.getString(FORUM_NAME);
|
||||
byte[] forumSalt = d.getRaw(FORUM_SALT);
|
||||
|
||||
int intState = d.getLong(STATE).intValue();
|
||||
if (d.getBoolean(IS_SHARER)) {
|
||||
SharerSessionState.State state =
|
||||
SharerSessionState.State.fromValue(intState);
|
||||
return new SharerSessionState(sessionId, messageId, groupId, state,
|
||||
contactId, forumId, forumName, forumSalt);
|
||||
} else {
|
||||
InviteeSessionState.State state =
|
||||
InviteeSessionState.State.fromValue(intState);
|
||||
return new InviteeSessionState(sessionId, messageId, groupId, state,
|
||||
contactId, forumId, forumName, forumSalt);
|
||||
}
|
||||
}
|
||||
|
||||
public BdfDictionary toBdfDictionary() {
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put(SESSION_ID, getSessionId());
|
||||
d.put(STORAGE_ID, getStorageId());
|
||||
d.put(GROUP_ID, getGroupId());
|
||||
d.put(CONTACT_ID, getContactId().getInt());
|
||||
d.put(FORUM_ID, getForumId());
|
||||
d.put(FORUM_NAME, getForumName());
|
||||
d.put(FORUM_SALT, getForumSalt());
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
public SessionId getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public MessageId getStorageId() {
|
||||
return storageId;
|
||||
}
|
||||
|
||||
public GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public GroupId getForumId() {
|
||||
return forumId;
|
||||
}
|
||||
|
||||
public String getForumName() {
|
||||
return forumName;
|
||||
}
|
||||
|
||||
public byte[] getForumSalt() {
|
||||
return forumSalt;
|
||||
}
|
||||
|
||||
public void setTask(int task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public int getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,8 +9,6 @@ import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.ForumInvitationReceivedEvent;
|
||||
import org.briarproject.api.forum.Forum;
|
||||
import org.briarproject.api.forum.ForumFactory;
|
||||
import org.briarproject.api.forum.InviteeAction;
|
||||
import org.briarproject.api.forum.InviteeProtocolState;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -19,9 +17,6 @@ import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
|
||||
import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
|
||||
@@ -29,25 +24,25 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_WITH_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TYPE;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_ABORT;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_ACCEPT;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_DECLINE;
|
||||
import static org.briarproject.api.forum.InviteeAction.LOCAL_LEAVE;
|
||||
import static org.briarproject.api.forum.InviteeAction.REMOTE_INVITATION;
|
||||
import static org.briarproject.api.forum.InviteeAction.REMOTE_LEAVE;
|
||||
import static org.briarproject.api.forum.InviteeProtocolState.ERROR;
|
||||
import static org.briarproject.api.forum.InviteeProtocolState.FINISHED;
|
||||
import static org.briarproject.api.forum.InviteeProtocolState.LEFT;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_ABORT;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_ACCEPT;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_DECLINE;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_LEAVE;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.REMOTE_INVITATION;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.REMOTE_LEAVE;
|
||||
import static org.briarproject.forum.InviteeSessionState.State;
|
||||
import static org.briarproject.forum.InviteeSessionState.State.ERROR;
|
||||
import static org.briarproject.forum.InviteeSessionState.State.FINISHED;
|
||||
import static org.briarproject.forum.InviteeSessionState.State.LEFT;
|
||||
|
||||
public class InviteeEngine
|
||||
implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
|
||||
implements ProtocolEngine<BdfDictionary, InviteeSessionState, BdfDictionary> {
|
||||
|
||||
private final ForumFactory forumFactory;
|
||||
private static final Logger LOG =
|
||||
@@ -58,16 +53,15 @@ public class InviteeEngine
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onLocalAction(
|
||||
BdfDictionary localState, BdfDictionary localAction) {
|
||||
public StateUpdate<InviteeSessionState, BdfDictionary> onLocalAction(
|
||||
InviteeSessionState localState, BdfDictionary localAction) {
|
||||
|
||||
try {
|
||||
InviteeProtocolState currentState =
|
||||
getState(localState.getLong(STATE));
|
||||
State currentState = localState.getState();
|
||||
long type = localAction.getLong(TYPE);
|
||||
InviteeAction action = InviteeAction.getLocal(type);
|
||||
InviteeProtocolState nextState = currentState.next(action);
|
||||
localState.put(STATE, nextState.getValue());
|
||||
Action action = Action.getLocal(type);
|
||||
State nextState = currentState.next(action);
|
||||
localState.setState(nextState);
|
||||
|
||||
if (action == LOCAL_ABORT && currentState != ERROR) {
|
||||
return abortSession(currentState, localState);
|
||||
@@ -85,14 +79,14 @@ public class InviteeEngine
|
||||
|
||||
if (action == LOCAL_ACCEPT || action == LOCAL_DECLINE) {
|
||||
BdfDictionary msg = BdfDictionary.of(
|
||||
new BdfEntry(SESSION_ID, localState.getRaw(SESSION_ID)),
|
||||
new BdfEntry(GROUP_ID, localState.getRaw(GROUP_ID))
|
||||
new BdfEntry(SESSION_ID, localState.getSessionId()),
|
||||
new BdfEntry(GROUP_ID, localState.getGroupId())
|
||||
);
|
||||
if (action == LOCAL_ACCEPT) {
|
||||
localState.put(TASK, TASK_ADD_SHARED_FORUM);
|
||||
localState.setTask(TASK_ADD_SHARED_FORUM);
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_ACCEPT);
|
||||
} else {
|
||||
localState.put(TASK,
|
||||
localState.setTask(
|
||||
TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US);
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_DECLINE);
|
||||
}
|
||||
@@ -102,15 +96,15 @@ public class InviteeEngine
|
||||
else if (action == LOCAL_LEAVE) {
|
||||
BdfDictionary msg = new BdfDictionary();
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_LEAVE);
|
||||
msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
|
||||
msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
|
||||
msg.put(SESSION_ID, localState.getSessionId());
|
||||
msg.put(GROUP_ID, localState.getGroupId());
|
||||
messages = Collections.singletonList(msg);
|
||||
logLocalAction(currentState, localState, msg);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown Local Action");
|
||||
}
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(false,
|
||||
return new StateUpdate<InviteeSessionState, BdfDictionary>(false,
|
||||
false, localState, messages, events);
|
||||
} catch (FormatException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
@@ -118,16 +112,15 @@ public class InviteeEngine
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onMessageReceived(
|
||||
BdfDictionary localState, BdfDictionary msg) {
|
||||
public StateUpdate<InviteeSessionState, BdfDictionary> onMessageReceived(
|
||||
InviteeSessionState localState, BdfDictionary msg) {
|
||||
|
||||
try {
|
||||
InviteeProtocolState currentState =
|
||||
getState(localState.getLong(STATE));
|
||||
State currentState = localState.getState();
|
||||
long type = msg.getLong(TYPE);
|
||||
InviteeAction action = InviteeAction.getRemote(type);
|
||||
InviteeProtocolState nextState = currentState.next(action);
|
||||
localState.put(STATE, nextState.getValue());
|
||||
Action action = Action.getRemote(type);
|
||||
State nextState = currentState.next(action);
|
||||
localState.setState(nextState);
|
||||
|
||||
logMessageReceived(currentState, nextState, type, msg);
|
||||
|
||||
@@ -149,7 +142,7 @@ public class InviteeEngine
|
||||
}
|
||||
// the sharer left the forum she had shared with us
|
||||
else if (action == REMOTE_LEAVE && currentState == FINISHED) {
|
||||
localState.put(TASK, TASK_UNSHARE_FORUM_SHARED_WITH_US);
|
||||
localState.setTask(TASK_UNSHARE_FORUM_SHARED_WITH_US);
|
||||
}
|
||||
else if (currentState == FINISHED) {
|
||||
// ignore and delete messages coming in while in that state
|
||||
@@ -158,31 +151,30 @@ public class InviteeEngine
|
||||
}
|
||||
// the sharer left the forum before we couldn't even respond
|
||||
else if (action == REMOTE_LEAVE) {
|
||||
localState.put(TASK, TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US);
|
||||
localState.setTask(TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US);
|
||||
}
|
||||
// we have just received our invitation
|
||||
else if (action == REMOTE_INVITATION) {
|
||||
localState.put(TASK, TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US);
|
||||
Forum forum = forumFactory
|
||||
.createForum(localState.getString(FORUM_NAME),
|
||||
localState.getRaw(FORUM_SALT));
|
||||
ContactId contactId = new ContactId(
|
||||
localState.getLong(CONTACT_ID).intValue());
|
||||
.createForum(localState.getForumName(),
|
||||
localState.getForumSalt());
|
||||
localState.setTask(TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US);
|
||||
ContactId contactId = localState.getContactId();
|
||||
Event event = new ForumInvitationReceivedEvent(forum, contactId);
|
||||
events = Collections.singletonList(event);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Bad state");
|
||||
}
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(deleteMsg,
|
||||
return new StateUpdate<InviteeSessionState, BdfDictionary>(deleteMsg,
|
||||
false, localState, messages, events);
|
||||
} catch (FormatException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logLocalAction(InviteeProtocolState state,
|
||||
BdfDictionary localState, BdfDictionary msg) {
|
||||
private void logLocalAction(State state,
|
||||
InviteeSessionState localState, BdfDictionary msg) {
|
||||
|
||||
if (!LOG.isLoggable(INFO)) return;
|
||||
|
||||
@@ -194,16 +186,16 @@ public class InviteeEngine
|
||||
" with session ID " +
|
||||
Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
|
||||
Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
|
||||
"Moving on to state " +
|
||||
getState(localState.getLong(STATE)).name()
|
||||
"Moving on to state " + localState.getState().name()
|
||||
);
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logMessageReceived(InviteeProtocolState currentState,
|
||||
InviteeProtocolState nextState, long type, BdfDictionary msg) {
|
||||
private void logMessageReceived(State currentState, State nextState,
|
||||
long type, BdfDictionary msg) {
|
||||
|
||||
if (!LOG.isLoggable(INFO)) return;
|
||||
|
||||
try {
|
||||
@@ -224,8 +216,8 @@ public class InviteeEngine
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onMessageDelivered(
|
||||
BdfDictionary localState, BdfDictionary delivered) {
|
||||
public StateUpdate<InviteeSessionState, BdfDictionary> onMessageDelivered(
|
||||
InviteeSessionState localState, BdfDictionary delivered) {
|
||||
try {
|
||||
return noUpdate(localState, false);
|
||||
} catch (FormatException e) {
|
||||
@@ -234,37 +226,33 @@ public class InviteeEngine
|
||||
}
|
||||
}
|
||||
|
||||
private InviteeProtocolState getState(Long state) {
|
||||
return InviteeProtocolState.fromValue(state.intValue());
|
||||
}
|
||||
|
||||
private StateUpdate<BdfDictionary, BdfDictionary> abortSession(
|
||||
InviteeProtocolState currentState, BdfDictionary localState)
|
||||
private StateUpdate<InviteeSessionState, BdfDictionary> abortSession(
|
||||
State currentState, InviteeSessionState localState)
|
||||
throws FormatException {
|
||||
|
||||
if (LOG.isLoggable(WARNING)) {
|
||||
LOG.warning("Aborting protocol session " +
|
||||
Arrays.hashCode(localState.getRaw(SESSION_ID)) +
|
||||
localState.getSessionId().hashCode() +
|
||||
" in state " + currentState.name());
|
||||
}
|
||||
|
||||
localState.put(STATE, ERROR.getValue());
|
||||
localState.setState(ERROR);
|
||||
BdfDictionary msg = new BdfDictionary();
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_ABORT);
|
||||
msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
|
||||
msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
|
||||
msg.put(SESSION_ID, localState.getSessionId());
|
||||
msg.put(GROUP_ID, localState.getGroupId());
|
||||
List<BdfDictionary> messages = Collections.singletonList(msg);
|
||||
|
||||
List<Event> events = Collections.emptyList();
|
||||
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(false, false,
|
||||
return new StateUpdate<InviteeSessionState, BdfDictionary>(false, false,
|
||||
localState, messages, events);
|
||||
}
|
||||
|
||||
private StateUpdate<BdfDictionary, BdfDictionary> noUpdate(
|
||||
BdfDictionary localState, boolean delete) throws FormatException {
|
||||
private StateUpdate<InviteeSessionState, BdfDictionary> noUpdate(
|
||||
InviteeSessionState localState, boolean delete) throws FormatException {
|
||||
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(delete, false,
|
||||
return new StateUpdate<InviteeSessionState, BdfDictionary>(delete, false,
|
||||
localState, Collections.<BdfDictionary>emptyList(),
|
||||
Collections.<Event>emptyList());
|
||||
}
|
||||
|
||||
130
briar-core/src/org/briarproject/forum/InviteeSessionState.java
Normal file
130
briar-core/src/org/briarproject/forum/InviteeSessionState.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package org.briarproject.forum;
|
||||
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_ACCEPT;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_DECLINE;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.LOCAL_LEAVE;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.REMOTE_INVITATION;
|
||||
import static org.briarproject.forum.InviteeSessionState.Action.REMOTE_LEAVE;
|
||||
|
||||
// This class is not thread-safe
|
||||
public class InviteeSessionState extends ForumSharingSessionState {
|
||||
|
||||
private State state;
|
||||
|
||||
public InviteeSessionState(SessionId sessionId, MessageId storageId,
|
||||
GroupId groupId, State state, ContactId contactId, GroupId forumId,
|
||||
String forumName, byte[] forumSalt) {
|
||||
|
||||
super(sessionId, storageId, groupId, contactId, forumId, forumName,
|
||||
forumSalt);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public BdfDictionary toBdfDictionary() {
|
||||
BdfDictionary d = super.toBdfDictionary();
|
||||
d.put(STATE, getState().getValue());
|
||||
d.put(IS_SHARER, false);
|
||||
return d;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
ERROR(0),
|
||||
AWAIT_INVITATION(1) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == REMOTE_INVITATION) return AWAIT_LOCAL_RESPONSE;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
AWAIT_LOCAL_RESPONSE(2) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_ACCEPT || a == LOCAL_DECLINE) return FINISHED;
|
||||
if (a == REMOTE_LEAVE) return LEFT;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
FINISHED(3) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
|
||||
return FINISHED;
|
||||
}
|
||||
},
|
||||
LEFT(4) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_LEAVE) return ERROR;
|
||||
return LEFT;
|
||||
}
|
||||
};
|
||||
|
||||
private final int value;
|
||||
|
||||
State(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static State fromValue(int value) {
|
||||
for (State s : values()) {
|
||||
if (s.value == value) return s;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public State next(Action a) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
LOCAL_ACCEPT,
|
||||
LOCAL_DECLINE,
|
||||
LOCAL_LEAVE,
|
||||
LOCAL_ABORT,
|
||||
REMOTE_INVITATION,
|
||||
REMOTE_LEAVE,
|
||||
REMOTE_ABORT;
|
||||
|
||||
public static Action getLocal(long type) {
|
||||
if (type == SHARE_MSG_TYPE_ACCEPT) return LOCAL_ACCEPT;
|
||||
if (type == SHARE_MSG_TYPE_DECLINE) return LOCAL_DECLINE;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Action getRemote(long type) {
|
||||
if (type == SHARE_MSG_TYPE_INVITATION) return REMOTE_INVITATION;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,8 +6,7 @@ import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
|
||||
import org.briarproject.api.forum.SharerAction;
|
||||
import org.briarproject.api.forum.SharerProtocolState;
|
||||
import static org.briarproject.forum.SharerSessionState.Action;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -16,7 +15,6 @@ import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
|
||||
import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
|
||||
import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
|
||||
@@ -27,40 +25,38 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_SHARE_FORUM;
|
||||
import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_BY_US;
|
||||
import static org.briarproject.api.forum.ForumConstants.TYPE;
|
||||
import static org.briarproject.api.forum.SharerAction.LOCAL_ABORT;
|
||||
import static org.briarproject.api.forum.SharerAction.LOCAL_INVITATION;
|
||||
import static org.briarproject.api.forum.SharerAction.LOCAL_LEAVE;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_ACCEPT;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_DECLINE;
|
||||
import static org.briarproject.api.forum.SharerAction.REMOTE_LEAVE;
|
||||
import static org.briarproject.api.forum.SharerProtocolState.ERROR;
|
||||
import static org.briarproject.api.forum.SharerProtocolState.FINISHED;
|
||||
import static org.briarproject.api.forum.SharerProtocolState.LEFT;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.LOCAL_ABORT;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.LOCAL_INVITATION;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.LOCAL_LEAVE;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_ACCEPT;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_DECLINE;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_LEAVE;
|
||||
import static org.briarproject.forum.SharerSessionState.State;
|
||||
import static org.briarproject.forum.SharerSessionState.State.ERROR;
|
||||
import static org.briarproject.forum.SharerSessionState.State.FINISHED;
|
||||
import static org.briarproject.forum.SharerSessionState.State.LEFT;
|
||||
|
||||
public class SharerEngine
|
||||
implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
|
||||
implements ProtocolEngine<BdfDictionary, SharerSessionState, BdfDictionary> {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(SharerEngine.class.getName());
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onLocalAction(
|
||||
BdfDictionary localState, BdfDictionary localAction) {
|
||||
public StateUpdate<SharerSessionState, BdfDictionary> onLocalAction(
|
||||
SharerSessionState localState, BdfDictionary localAction) {
|
||||
|
||||
try {
|
||||
SharerProtocolState currentState =
|
||||
getState(localState.getLong(STATE));
|
||||
State currentState = localState.getState();
|
||||
long type = localAction.getLong(TYPE);
|
||||
SharerAction action = SharerAction.getLocal(type);
|
||||
SharerProtocolState nextState = currentState.next(action);
|
||||
localState.put(STATE, nextState.getValue());
|
||||
Action action = Action.getLocal(type);
|
||||
State nextState = currentState.next(action);
|
||||
localState.setState(nextState);
|
||||
|
||||
if (action == LOCAL_ABORT && currentState != ERROR) {
|
||||
return abortSession(currentState, localState);
|
||||
@@ -79,32 +75,32 @@ public class SharerEngine
|
||||
if (action == LOCAL_INVITATION) {
|
||||
BdfDictionary msg = new BdfDictionary();
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_INVITATION);
|
||||
msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
|
||||
msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
|
||||
msg.put(FORUM_NAME, localState.getString(FORUM_NAME));
|
||||
msg.put(FORUM_SALT, localState.getRaw(FORUM_SALT));
|
||||
msg.put(SESSION_ID, localState.getSessionId());
|
||||
msg.put(GROUP_ID, localState.getGroupId());
|
||||
msg.put(FORUM_NAME, localState.getForumName());
|
||||
msg.put(FORUM_SALT, localState.getForumSalt());
|
||||
if (localAction.containsKey(INVITATION_MSG)) {
|
||||
msg.put(INVITATION_MSG,
|
||||
localAction.getString(INVITATION_MSG));
|
||||
}
|
||||
messages = Collections.singletonList(msg);
|
||||
logLocalAction(currentState, localState, msg);
|
||||
logLocalAction(currentState, nextState, msg);
|
||||
|
||||
// remember that we offered to share this forum
|
||||
localState.put(TASK, TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US);
|
||||
localState.setTask(TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US);
|
||||
}
|
||||
else if (action == LOCAL_LEAVE) {
|
||||
BdfDictionary msg = new BdfDictionary();
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_LEAVE);
|
||||
msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
|
||||
msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
|
||||
msg.put(SESSION_ID, localState.getSessionId());
|
||||
msg.put(GROUP_ID, localState.getGroupId());
|
||||
messages = Collections.singletonList(msg);
|
||||
logLocalAction(currentState, localState, msg);
|
||||
logLocalAction(currentState, nextState, msg);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown Local Action");
|
||||
}
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(false,
|
||||
return new StateUpdate<SharerSessionState, BdfDictionary>(false,
|
||||
false, localState, messages, events);
|
||||
} catch (FormatException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
@@ -112,16 +108,15 @@ public class SharerEngine
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onMessageReceived(
|
||||
BdfDictionary localState, BdfDictionary msg) {
|
||||
public StateUpdate<SharerSessionState, BdfDictionary> onMessageReceived(
|
||||
SharerSessionState localState, BdfDictionary msg) {
|
||||
|
||||
try {
|
||||
SharerProtocolState currentState =
|
||||
getState(localState.getLong(STATE));
|
||||
State currentState = localState.getState();
|
||||
long type = msg.getLong(TYPE);
|
||||
SharerAction action = SharerAction.getRemote(type);
|
||||
SharerProtocolState nextState = currentState.next(action);
|
||||
localState.put(STATE, nextState.getValue());
|
||||
Action action = Action.getRemote(type);
|
||||
State nextState = currentState.next(action);
|
||||
localState.setState(nextState);
|
||||
|
||||
logMessageReceived(currentState, nextState, type, msg);
|
||||
|
||||
@@ -141,7 +136,7 @@ public class SharerEngine
|
||||
deleteMsg = true;
|
||||
}
|
||||
else if (action == REMOTE_LEAVE) {
|
||||
localState.put(TASK, TASK_UNSHARE_FORUM_SHARED_BY_US);
|
||||
localState.setTask(TASK_UNSHARE_FORUM_SHARED_BY_US);
|
||||
}
|
||||
else if (currentState == FINISHED) {
|
||||
// ignore and delete messages coming in while in that state
|
||||
@@ -151,30 +146,29 @@ public class SharerEngine
|
||||
// we have sent our invitation and just got a response
|
||||
else if (action == REMOTE_ACCEPT || action == REMOTE_DECLINE) {
|
||||
if (action == REMOTE_ACCEPT) {
|
||||
localState.put(TASK, TASK_SHARE_FORUM);
|
||||
localState.setTask(TASK_SHARE_FORUM);
|
||||
} else {
|
||||
// this ensures that the forum can be shared again
|
||||
localState.put(TASK,
|
||||
localState.setTask(
|
||||
TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US);
|
||||
}
|
||||
String name = localState.getString(FORUM_NAME);
|
||||
ContactId c = new ContactId(
|
||||
localState.getLong(CONTACT_ID).intValue());
|
||||
String name = localState.getForumName();
|
||||
ContactId c = localState.getContactId();
|
||||
Event event = new ForumInvitationResponseReceivedEvent(name, c);
|
||||
events = Collections.singletonList(event);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Bad state");
|
||||
}
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(deleteMsg,
|
||||
return new StateUpdate<SharerSessionState, BdfDictionary>(deleteMsg,
|
||||
false, localState, messages, events);
|
||||
} catch (FormatException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logLocalAction(SharerProtocolState state,
|
||||
BdfDictionary localState, BdfDictionary msg) {
|
||||
private void logLocalAction(State currentState, State nextState,
|
||||
BdfDictionary msg) {
|
||||
|
||||
if (!LOG.isLoggable(INFO)) return;
|
||||
|
||||
@@ -182,20 +176,20 @@ public class SharerEngine
|
||||
if (msg.getLong(TYPE, -1L) == SHARE_MSG_TYPE_LEAVE) a = "leave";
|
||||
|
||||
try {
|
||||
LOG.info("Sending " + a + " in state " + state.name() +
|
||||
LOG.info("Sending " + a + " in state " + currentState.name() +
|
||||
" with session ID " +
|
||||
Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
|
||||
Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
|
||||
"Moving on to state " +
|
||||
getState(localState.getLong(STATE)).name()
|
||||
"Moving on to state " + nextState.name()
|
||||
);
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logMessageReceived(SharerProtocolState currentState,
|
||||
SharerProtocolState nextState, long type, BdfDictionary msg) {
|
||||
private void logMessageReceived(State currentState, State nextState,
|
||||
long type, BdfDictionary msg) {
|
||||
|
||||
if (!LOG.isLoggable(INFO)) return;
|
||||
|
||||
try {
|
||||
@@ -217,8 +211,8 @@ public class SharerEngine
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateUpdate<BdfDictionary, BdfDictionary> onMessageDelivered(
|
||||
BdfDictionary localState, BdfDictionary delivered) {
|
||||
public StateUpdate<SharerSessionState, BdfDictionary> onMessageDelivered(
|
||||
SharerSessionState localState, BdfDictionary delivered) {
|
||||
try {
|
||||
return noUpdate(localState, false);
|
||||
} catch (FormatException e) {
|
||||
@@ -227,38 +221,36 @@ public class SharerEngine
|
||||
}
|
||||
}
|
||||
|
||||
private SharerProtocolState getState(Long state) {
|
||||
return SharerProtocolState.fromValue(state.intValue());
|
||||
}
|
||||
|
||||
private StateUpdate<BdfDictionary, BdfDictionary> abortSession(
|
||||
SharerProtocolState currentState, BdfDictionary localState)
|
||||
private StateUpdate<SharerSessionState, BdfDictionary> abortSession(
|
||||
State currentState, SharerSessionState localState)
|
||||
throws FormatException {
|
||||
|
||||
if (LOG.isLoggable(WARNING)) {
|
||||
LOG.warning("Aborting protocol session " +
|
||||
Arrays.hashCode(localState.getRaw(SESSION_ID)) +
|
||||
localState.getSessionId().hashCode() +
|
||||
" in state " + currentState.name());
|
||||
}
|
||||
|
||||
localState.put(STATE, ERROR.getValue());
|
||||
localState.setState(ERROR);
|
||||
BdfDictionary msg = new BdfDictionary();
|
||||
msg.put(TYPE, SHARE_MSG_TYPE_ABORT);
|
||||
msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
|
||||
msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
|
||||
msg.put(SESSION_ID, localState.getSessionId());
|
||||
msg.put(GROUP_ID, localState.getGroupId());
|
||||
List<BdfDictionary> messages = Collections.singletonList(msg);
|
||||
|
||||
List<Event> events = Collections.emptyList();
|
||||
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(false, false,
|
||||
return new StateUpdate<SharerSessionState, BdfDictionary>(false, false,
|
||||
localState, messages, events);
|
||||
}
|
||||
|
||||
private StateUpdate<BdfDictionary, BdfDictionary> noUpdate(
|
||||
BdfDictionary localState, boolean delete) throws FormatException {
|
||||
private StateUpdate<SharerSessionState, BdfDictionary> noUpdate(
|
||||
SharerSessionState localState, boolean delete)
|
||||
throws FormatException {
|
||||
|
||||
return new StateUpdate<BdfDictionary, BdfDictionary>(delete, false,
|
||||
return new StateUpdate<SharerSessionState, BdfDictionary>(delete, false,
|
||||
localState, Collections.<BdfDictionary>emptyList(),
|
||||
Collections.<Event>emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
130
briar-core/src/org/briarproject/forum/SharerSessionState.java
Normal file
130
briar-core/src/org/briarproject/forum/SharerSessionState.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package org.briarproject.forum;
|
||||
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
|
||||
import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
|
||||
import static org.briarproject.api.forum.ForumConstants.STATE;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.LOCAL_INVITATION;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.LOCAL_LEAVE;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_ACCEPT;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_DECLINE;
|
||||
import static org.briarproject.forum.SharerSessionState.Action.REMOTE_LEAVE;
|
||||
|
||||
// This class is not thread-safe
|
||||
public class SharerSessionState extends ForumSharingSessionState {
|
||||
|
||||
private State state;
|
||||
|
||||
public SharerSessionState(SessionId sessionId, MessageId storageId,
|
||||
GroupId groupId, State state, ContactId contactId, GroupId forumId,
|
||||
String forumName, byte[] forumSalt) {
|
||||
|
||||
super(sessionId, storageId, groupId, contactId, forumId, forumName,
|
||||
forumSalt);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public BdfDictionary toBdfDictionary() {
|
||||
BdfDictionary d = super.toBdfDictionary();
|
||||
d.put(STATE, getState().getValue());
|
||||
d.put(IS_SHARER, true);
|
||||
return d;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
ERROR(0),
|
||||
PREPARE_INVITATION(1) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_INVITATION) return AWAIT_RESPONSE;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
AWAIT_RESPONSE(2) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == REMOTE_ACCEPT || a == REMOTE_DECLINE) return FINISHED;
|
||||
if (a == LOCAL_LEAVE) return LEFT;
|
||||
return ERROR;
|
||||
}
|
||||
},
|
||||
FINISHED(3) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
|
||||
return FINISHED;
|
||||
}
|
||||
},
|
||||
LEFT(4) {
|
||||
@Override
|
||||
public State next(Action a) {
|
||||
if (a == LOCAL_LEAVE) return ERROR;
|
||||
return LEFT;
|
||||
}
|
||||
};
|
||||
|
||||
private final int value;
|
||||
|
||||
State(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static State fromValue(int value) {
|
||||
for (State s : values()) {
|
||||
if (s.value == value) return s;
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public State next(Action a) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
LOCAL_INVITATION,
|
||||
LOCAL_LEAVE,
|
||||
LOCAL_ABORT,
|
||||
REMOTE_ACCEPT,
|
||||
REMOTE_DECLINE,
|
||||
REMOTE_LEAVE,
|
||||
REMOTE_ABORT;
|
||||
|
||||
public static Action getLocal(long type) {
|
||||
if (type == SHARE_MSG_TYPE_INVITATION) return LOCAL_INVITATION;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Action getRemote(long type) {
|
||||
if (type == SHARE_MSG_TYPE_ACCEPT) return REMOTE_ACCEPT;
|
||||
if (type == SHARE_MSG_TYPE_DECLINE) return REMOTE_DECLINE;
|
||||
if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
|
||||
if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user