use of org.signal.storageservice.protos.groups.local.DecryptedGroup in project Signal-Android by WhisperSystems.
the class GroupsV1MigrationUtil method performLocalMigration.
@Nullable
private static DecryptedGroup performLocalMigration(@NonNull Context context, @NonNull GroupId.V1 gv1Id, long threadId, @NonNull Recipient groupRecipient) throws IOException, GroupChangeBusyException {
Log.i(TAG, "performLocalMigration(" + gv1Id + ", " + threadId + ", " + groupRecipient.getId());
try (Closeable ignored = GroupsV2ProcessingLock.acquireGroupProcessingLock()) {
DecryptedGroup decryptedGroup;
try {
decryptedGroup = GroupManager.addedGroupVersion(context, gv1Id.deriveV2MigrationMasterKey());
} catch (GroupDoesNotExistException e) {
throw new IOException("[Local] The group should exist already!");
} catch (GroupNotAMemberException e) {
Log.w(TAG, "[Local] We are not in the group. Doing a local leave.");
handleLeftBehind(context, gv1Id, groupRecipient, threadId);
return null;
}
Log.i(TAG, "[Local] Migrating group over to the version we were added to: V" + decryptedGroup.getRevision());
SignalDatabase.groups().migrateToV2(threadId, gv1Id, decryptedGroup);
Log.i(TAG, "[Local] Applying all changes since V" + decryptedGroup.getRevision());
try {
GroupManager.updateGroupFromServer(context, gv1Id.deriveV2MigrationMasterKey(), LATEST, System.currentTimeMillis(), null);
} catch (GroupChangeBusyException | GroupNotAMemberException e) {
Log.w(TAG, e);
}
return decryptedGroup;
}
}
use of org.signal.storageservice.protos.groups.local.DecryptedGroup in project Signal-Android by WhisperSystems.
the class GroupStateMapper method processChanges.
@NonNull
private static AdvanceGroupStateResult processChanges(@NonNull GlobalGroupState inputState, int maximumRevisionToApply) {
HashMap<Integer, ServerGroupLogEntry> statesToApplyNow = new HashMap<>(inputState.getServerHistory().size());
ArrayList<ServerGroupLogEntry> statesToApplyLater = new ArrayList<>(inputState.getServerHistory().size());
DecryptedGroup current = inputState.getLocalState();
StateChain<DecryptedGroup, DecryptedGroupChange> stateChain = createNewMapper();
if (inputState.getServerHistory().isEmpty()) {
return new AdvanceGroupStateResult(Collections.emptyList(), new GlobalGroupState(current, Collections.emptyList()));
}
for (ServerGroupLogEntry entry : inputState.getServerHistory()) {
if (entry.getRevision() > maximumRevisionToApply) {
statesToApplyLater.add(entry);
} else {
statesToApplyNow.put(entry.getRevision(), entry);
}
}
Collections.sort(statesToApplyLater, BY_REVISION);
final int from = Math.max(0, inputState.getEarliestRevisionNumber());
final int to = Math.min(inputState.getLatestRevisionNumber(), maximumRevisionToApply);
if (current != null && current.getRevision() == PLACEHOLDER_REVISION) {
Log.i(TAG, "Ignoring place holder group state");
} else {
stateChain.push(current, null);
}
for (int revision = from; revision >= 0 && revision <= to; revision++) {
ServerGroupLogEntry entry = statesToApplyNow.get(revision);
if (entry == null) {
Log.w(TAG, "Could not find group log on server V" + revision);
continue;
}
if (stateChain.getLatestState() == null && entry.getGroup() != null && current != null && current.getRevision() == PLACEHOLDER_REVISION) {
DecryptedGroup previousState = DecryptedGroup.newBuilder(entry.getGroup()).setTitle(current.getTitle()).setAvatar(current.getAvatar()).build();
stateChain.push(previousState, null);
}
stateChain.push(entry.getGroup(), entry.getChange());
}
List<StateChain.Pair<DecryptedGroup, DecryptedGroupChange>> mapperList = stateChain.getList();
List<LocalGroupLogEntry> appliedChanges = new ArrayList<>(mapperList.size());
for (StateChain.Pair<DecryptedGroup, DecryptedGroupChange> entry : mapperList) {
if (current == null || entry.getDelta() != null) {
appliedChanges.add(new LocalGroupLogEntry(entry.getState(), entry.getDelta()));
}
}
return new AdvanceGroupStateResult(appliedChanges, new GlobalGroupState(stateChain.getLatestState(), statesToApplyLater));
}
use of org.signal.storageservice.protos.groups.local.DecryptedGroup in project Signal-Android by signalapp.
the class GroupManagerV2 method addedGroupVersion.
@WorkerThread
@NonNull
DecryptedGroup addedGroupVersion(@NonNull GroupMasterKey groupMasterKey) throws GroupNotAMemberException, IOException, GroupDoesNotExistException {
GroupsV2StateProcessor.StateProcessorForGroup stateProcessorForGroup = new GroupsV2StateProcessor(context).forGroup(groupMasterKey);
DecryptedGroup latest = stateProcessorForGroup.getCurrentGroupStateFromServer();
if (latest.getRevision() == 0) {
return latest;
}
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.uuid());
if (!selfInFullMemberList.isPresent()) {
return latest;
}
DecryptedGroup joinedVersion = stateProcessorForGroup.getSpecificVersionFromServer(selfInFullMemberList.get().getJoinedAtRevision());
if (joinedVersion != null) {
return joinedVersion;
} else {
Log.w(TAG, "Unable to retreive exact version joined at, using latest");
return latest;
}
}
use of org.signal.storageservice.protos.groups.local.DecryptedGroup in project Signal-Android by signalapp.
the class GroupsV1MigrationUtil method performLocalMigration.
@Nullable
private static DecryptedGroup performLocalMigration(@NonNull Context context, @NonNull GroupId.V1 gv1Id, long threadId, @NonNull Recipient groupRecipient) throws IOException, GroupChangeBusyException {
Log.i(TAG, "performLocalMigration(" + gv1Id + ", " + threadId + ", " + groupRecipient.getId());
try (Closeable ignored = GroupsV2ProcessingLock.acquireGroupProcessingLock()) {
DecryptedGroup decryptedGroup;
try {
decryptedGroup = GroupManager.addedGroupVersion(context, gv1Id.deriveV2MigrationMasterKey());
} catch (GroupDoesNotExistException e) {
throw new IOException("[Local] The group should exist already!");
} catch (GroupNotAMemberException e) {
Log.w(TAG, "[Local] We are not in the group. Doing a local leave.");
handleLeftBehind(context, gv1Id, groupRecipient, threadId);
return null;
}
Log.i(TAG, "[Local] Migrating group over to the version we were added to: V" + decryptedGroup.getRevision());
SignalDatabase.groups().migrateToV2(threadId, gv1Id, decryptedGroup);
Log.i(TAG, "[Local] Applying all changes since V" + decryptedGroup.getRevision());
try {
GroupManager.updateGroupFromServer(context, gv1Id.deriveV2MigrationMasterKey(), LATEST, System.currentTimeMillis(), null);
} catch (GroupChangeBusyException | GroupNotAMemberException e) {
Log.w(TAG, e);
}
return decryptedGroup;
}
}
use of org.signal.storageservice.protos.groups.local.DecryptedGroup in project Signal-Android by signalapp.
the class PendingMemberInvitesRepository method getInvitees.
public void getInvitees(@NonNull Consumer<InviteeResult> onInviteesLoaded) {
executor.execute(() -> {
GroupDatabase groupDatabase = SignalDatabase.groups();
GroupDatabase.V2GroupProperties v2GroupProperties = groupDatabase.getGroup(groupId).get().requireV2GroupProperties();
DecryptedGroup decryptedGroup = v2GroupProperties.getDecryptedGroup();
List<DecryptedPendingMember> pendingMembersList = decryptedGroup.getPendingMembersList();
List<SinglePendingMemberInvitedByYou> byMe = new ArrayList<>(pendingMembersList.size());
List<MultiplePendingMembersInvitedByAnother> byOthers = new ArrayList<>(pendingMembersList.size());
ByteString self = Recipient.self().requireServiceId().toByteString();
boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self());
Stream.of(pendingMembersList).groupBy(DecryptedPendingMember::getAddedByUuid).forEach(g -> {
ByteString inviterUuid = g.getKey();
List<DecryptedPendingMember> invitedMembers = g.getValue();
if (self.equals(inviterUuid)) {
for (DecryptedPendingMember pendingMember : invitedMembers) {
try {
Recipient invitee = GroupProtoUtil.pendingMemberToRecipient(context, pendingMember);
UuidCiphertext uuidCipherText = new UuidCiphertext(pendingMember.getUuidCipherText().toByteArray());
byMe.add(new SinglePendingMemberInvitedByYou(invitee, uuidCipherText));
} catch (InvalidInputException e) {
Log.w(TAG, e);
}
}
} else {
Recipient inviter = GroupProtoUtil.uuidByteStringToRecipient(context, inviterUuid);
ArrayList<UuidCiphertext> uuidCipherTexts = new ArrayList<>(invitedMembers.size());
for (DecryptedPendingMember pendingMember : invitedMembers) {
try {
uuidCipherTexts.add(new UuidCiphertext(pendingMember.getUuidCipherText().toByteArray()));
} catch (InvalidInputException e) {
Log.w(TAG, e);
}
}
byOthers.add(new MultiplePendingMembersInvitedByAnother(inviter, uuidCipherTexts));
}
});
onInviteesLoaded.accept(new InviteeResult(byMe, byOthers, selfIsAdmin));
});
}
Aggregations