Merge pull request #213 from loki-project/database-3

Integrate Transaction Handling Utility
This commit is contained in:
Niels Andriesse 2020-06-15 14:04:20 +10:00 committed by GitHub
commit 136f9d9aec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
93 changed files with 813 additions and 766 deletions

View file

@ -7,7 +7,7 @@
<key>CarthageVersion</key>
<string>0.34.0</string>
<key>OSXVersion</key>
<string>10.15.4</string>
<string>10.15.5</string>
<key>WebRTCCommit</key>
<string>1445d719bf05280270e9f77576f80f973fd847f8 M73</string>
</dict>

View file

@ -1254,10 +1254,9 @@ static NSTimeInterval launchStartedAt;
if ([self.tsAccountManager isRegistered]) {
OWSLogInfo(@"localNumber: %@", [self.tsAccountManager localNumber]);
[self.primaryStorage.newDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[ExperienceUpgradeFinder.sharedManager markAllAsSeenWithTransaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[ExperienceUpgradeFinder.sharedManager markAllAsSeenWithTransaction:transaction];
} error:nil];
// Start running the disappearing messages job in case the newly registered user
// enables this feature
@ -1424,10 +1423,10 @@ static NSTimeInterval launchStartedAt;
BOOL isChatSetUp = [NSUserDefaults.standardUserDefaults boolForKey:userDefaultsKey];
if (!isChatSetUp || !chat.isDeletable) {
[LKPublicChatManager.shared addChatWithServer:chat.server channel:chat.channel name:chat.displayName];
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSGroupThread *thread = [TSGroupThread threadWithGroupId:[LKGroupUtilities getEncodedOpenGroupIDAsData:chat.id] transaction:transaction];
if (thread != nil) { [OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread]; }
}];
} error:nil];
[NSUserDefaults.standardUserDefaults setBool:YES forKey:userDefaultsKey];
}
}
@ -1466,9 +1465,9 @@ static NSTimeInterval launchStartedAt;
if (!isFeedSetUp || !feed.isDeletable) {
TSGroupModel *group = [[TSGroupModel alloc] initWithTitle:feed.displayName memberIds:@[ userHexEncodedPublicKey, feed.server ] image:nil groupId:[LKGroupUtilities getEncodedRSSFeedIDAsData:feed.id] groupType:rssFeed adminIds:@[ userHexEncodedPublicKey, feed.server ]];
__block TSGroupThread *thread;
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSGroupThread getOrCreateThreadWithGroupModel:group transaction:transaction];
}];
} error:nil];
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
[NSUserDefaults.standardUserDefaults setBool:YES forKey:userDefaultsKey];
}

View file

@ -112,7 +112,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
* We don't want to delete the session. Ref: SignalServiceKit/Loki/Docs/SessionReset.md
* ================
if firstAttempt {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
Logger.info("deleting sessions for recipient: \(self.recipientId)")
self.primaryStorage.deleteAllSessions(forContact: self.recipientId, protocolContext: transaction)
}
@ -127,7 +127,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
return self.messageSender.sendPromise(message: endSessionMessage)
}.done {
Logger.info("successfully sent EndSessionMessage.")
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
// Archive the just-created session since the recipient should delete their corresponding
// session upon receiving and decrypting our EndSession message.
// Otherwise if we send another message before them, they wont have the session to decrypt it.
@ -160,7 +160,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
}
override public func didSucceed() {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperationDidSucceed(self, transaction: transaction)
}
}
@ -168,7 +168,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
override public func didReportError(_ error: Error) {
Logger.debug("remainingRetries: \(self.remainingRetries)")
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperation(self, didReportError: error, transaction: transaction)
}
}
@ -192,7 +192,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
override public func didFail(error: Error) {
Logger.error("failed to send EndSessionMessage with error: \(error.localizedDescription)")
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperation(self, didFailWithError: error, transaction: transaction)
// Even though this is the failure handler - which means probably the recipient didn't receive the message

View file

@ -134,22 +134,23 @@ final class ConversationCell : UITableViewCell {
// MARK: Updating
private func update() {
AssertIsOnMainThread()
MentionsManager.populateUserPublicKeyCacheIfNeeded(for: threadViewModel.threadRecord.uniqueId!) // FIXME: This is a terrible place to do this
unreadMessagesIndicatorView.alpha = threadViewModel.hasUnreadMessages ? 1 : 0.0001 // Setting the alpha to exactly 0 causes an issue on iOS 12
profilePictureView.openGroupProfilePicture = nil
if threadViewModel.isGroupThread {
if threadViewModel.name == "Session Public Chat" {
if threadViewModel.name == "Loki Public Chat" {
profilePictureView.hexEncodedPublicKey = ""
profilePictureView.isRSSFeed = true
} else {
var users = MentionsManager.userPublicKeyCache[threadViewModel.threadRecord.uniqueId!] ?? []
users.remove(getUserHexEncodedPublicKey())
let randomUsers = users.sorted().prefix(2) // Sort to provide a level of stability
if !randomUsers.isEmpty {
profilePictureView.hexEncodedPublicKey = randomUsers[0]
profilePictureView.additionalHexEncodedPublicKey = randomUsers.count >= 2 ? randomUsers[1] : ""
if let openGroupProfilePicture = (threadViewModel.threadRecord as! TSGroupThread).groupModel.groupImage {
profilePictureView.openGroupProfilePicture = openGroupProfilePicture
} else {
profilePictureView.hexEncodedPublicKey = ""
profilePictureView.additionalHexEncodedPublicKey = ""
var users = MentionsManager.userPublicKeyCache[threadViewModel.threadRecord.uniqueId!] ?? []
users.remove(getUserHexEncodedPublicKey())
let randomUsers = users.sorted().prefix(2) // Sort to provide a level of stability
profilePictureView.hexEncodedPublicKey = randomUsers.count >= 1 ? randomUsers[0] : ""
profilePictureView.additionalHexEncodedPublicKey = randomUsers.count >= 2 ? randomUsers[1] : ""
}
profilePictureView.isRSSFeed = (threadViewModel.threadRecord as? TSGroupThread)?.isRSSFeed ?? false
}

View file

@ -180,7 +180,7 @@ final class ConversationTitleView : UIView {
if thread.groupModel.groupType == .closedGroup {
userCount = GroupUtilities.getClosedGroupMemberCount(thread)
} else if thread.groupModel.groupType == .openGroup {
storage.dbReadConnection.readWrite { transaction in
storage.dbReadConnection.read { transaction in
if let publicChat = LokiDatabaseUtilities.getPublicChat(for: self.thread.uniqueId!, in: transaction) {
userCount = storage.getUserCount(for: publicChat, in: transaction)
}

View file

@ -63,7 +63,7 @@ public final class LokiRSSFeedPoller : NSObject {
envelope.setSource(NSLocalizedString("Loki", comment: ""))
envelope.setSourceDevice(OWSDevicePrimaryDeviceId)
envelope.setContent(try! content.build().serializedData())
OWSPrimaryStorage.shared().dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
SSKEnvironment.shared.messageManager.throws_processEnvelope(try! envelope.build(), plaintextData: try! content.build().serializedData(), wasReceivedByUD: false, transaction: transaction, serverID: 0)
}
}

View file

@ -186,7 +186,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
SSKEnvironment.shared.messageSender.send(linkingAuthorizationMessage, success: {
let storage = OWSPrimaryStorage.shared()
let slaveHexEncodedPublicKey = deviceLink.slave.hexEncodedPublicKey
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
let thread = TSContactThread.getOrCreateThread(withContactId: slaveHexEncodedPublicKey, transaction: transaction)
thread.save(with: transaction)
}
@ -196,7 +196,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
let _ = SSKEnvironment.shared.syncManager.syncAllContacts()
}
let _ = SSKEnvironment.shared.syncManager.syncAllOpenGroups()
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
storage.setFriendRequestStatus(.friends, for: slaveHexEncodedPublicKey, transaction: transaction)
}
DispatchQueue.main.async {
@ -251,9 +251,8 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
session.markLinkingRequestAsProcessed() // Only relevant in master mode
delegate?.handleDeviceLinkingModalDismissed() // Only relevant in slave mode
if let deviceLink = deviceLink {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
storage.removePreKeyBundle(forContact: deviceLink.slave.hexEncodedPublicKey, transaction: transaction)
try! Storage.writeSync { transaction in
OWSPrimaryStorage.shared().removePreKeyBundle(forContact: deviceLink.slave.hexEncodedPublicKey, transaction: transaction)
}
}
dismiss(animated: true, completion: nil)

View file

@ -146,14 +146,14 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
let unlinkDeviceMessage = UnlinkDeviceMessage(thread: thread)
SSKEnvironment.shared.messageSender.send(unlinkDeviceMessage, success: {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
storage.removePreKeyBundle(forContact: linkedDeviceHexEncodedPublicKey, transaction: transaction)
storage.deleteAllSessions(forContact: linkedDeviceHexEncodedPublicKey, protocolContext: transaction)
}
}, failure: { _ in
print("[Loki] Failed to send unlink device message.")
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
storage.removePreKeyBundle(forContact: linkedDeviceHexEncodedPublicKey, transaction: transaction)
storage.deleteAllSessions(forContact: linkedDeviceHexEncodedPublicKey, protocolContext: transaction)
}

View file

@ -369,7 +369,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: ""), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
guard let self = self else { return }
self.editingDatabaseConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
if let publicChat = publicChat {
var messageIDs: Set<String> = []
thread.enumerateInteractions(with: transaction) { interaction, _ in

View file

@ -133,9 +133,12 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
isJoining = true
let channelID: UInt64 = 1
let urlAsString = url.absoluteString
let displayName = OWSProfileManager.shared().localProfileName()
// TODO: Profile picture & profile key
OWSPrimaryStorage.shared().dbReadWriteConnection.readWrite { transaction in
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let profileManager = OWSProfileManager.shared()
let displayName = profileManager.profileNameForRecipient(withID: userPublicKey)
let profilePictureURL = profileManager.profilePictureURL()
let profileKey = profileManager.localProfileKey().keyData
try! Storage.writeSync { transaction in
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: LokiPublicChatAPI.lastMessageServerIDCollection)
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: LokiPublicChatAPI.lastDeletionServerIDCollection)
}
@ -143,6 +146,7 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
.done(on: .main) { [weak self] _ in
let _ = LokiPublicChatAPI.getMessages(for: channelID, on: urlAsString)
let _ = LokiPublicChatAPI.setDisplayName(to: displayName, on: urlAsString)
let _ = LokiPublicChatAPI.setProfilePictureURL(to: profilePictureURL, using: profileKey, on: urlAsString)
let _ = LokiPublicChatAPI.join(channelID, on: urlAsString)
let syncManager = SSKEnvironment.shared.syncManager
let _ = syncManager.syncAllOpenGroups()

View file

@ -159,7 +159,7 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
let userHexEncodedPublicKey = getUserHexEncodedPublicKey()
let storage = OWSPrimaryStorage.shared()
var masterHexEncodedPublicKey = ""
storage.dbReadConnection.readWrite { transaction in
storage.dbReadConnection.read { transaction in
masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: userHexEncodedPublicKey, in: transaction) ?? userHexEncodedPublicKey
}
let members = selectedContacts + [ masterHexEncodedPublicKey ]

View file

@ -115,7 +115,7 @@ class ConversationViewItemActions: NSObject {
actions.append(deleteAction)
}
if isGroup && conversationViewItem.interaction.thread.name() == "Session Public Chat" {
if isGroup && conversationViewItem.interaction.thread.name() == "Loki Public Chat" {
let reportAction = MessageActionBuilder.report(conversationViewItem, delegate: delegate)
actions.append(reportAction)
}
@ -159,7 +159,7 @@ class ConversationViewItemActions: NSObject {
actions.append(deleteAction)
}
if isGroup && conversationViewItem.interaction.thread.name() == "Session Public Chat" {
if isGroup && conversationViewItem.interaction.thread.name() == "Loki Public Chat" {
let reportAction = MessageActionBuilder.report(conversationViewItem, delegate: delegate)
actions.append(reportAction)
}
@ -192,7 +192,7 @@ class ConversationViewItemActions: NSObject {
actions.append(deleteAction)
}
if isGroup && conversationViewItem.interaction.thread.name() == "Session Public Chat" {
if isGroup && conversationViewItem.interaction.thread.name() == "Loki Public Chat" {
let reportAction = MessageActionBuilder.report(conversationViewItem, delegate: delegate)
actions.append(reportAction)
}

View file

@ -659,7 +659,7 @@ class NotificationActionHandler {
}
private func markAsRead(thread: TSThread) -> Promise<Void> {
return dbConnection.readWritePromise { transaction in
return Storage.write { transaction in
thread.markAllAsRead(with: transaction)
}
}

View file

@ -1255,9 +1255,9 @@ typedef enum : NSUInteger {
- (void)restoreSession {
dispatch_async(dispatch_get_main_queue(), ^{
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKSessionManagementProtocol startSessionResetInThread:self.thread using:transaction];
}];
} error:nil];
});
}
@ -1926,10 +1926,9 @@ typedef enum : NSUInteger {
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"send_again")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self.editingDatabaseConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
}];
[actionSheet addAction:resendMessageAction];
@ -1980,10 +1979,9 @@ typedef enum : NSUInteger {
return;
}
TSContactThread *contactThread = (TSContactThread *)self.thread;
[self.editingDatabaseConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.sessionResetJobQueue addContactThread:contactThread transaction:transaction];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.sessionResetJobQueue addContactThread:contactThread transaction:transaction];
}];
}];
[alert addAction:resetSessionAction];
@ -2358,12 +2356,11 @@ typedef enum : NSUInteger {
OWSLogInfo(@"Blocking an unknown user.");
[self.blockingManager addBlockedPhoneNumber:interaction.recipientId];
// Delete the offers.
[self.editingDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
contactThread.hasDismissedOffers = YES;
[contactThread saveWithTransaction:transaction];
[interaction removeWithTransaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
contactThread.hasDismissedOffers = YES;
[contactThread saveWithTransaction:transaction];
[interaction removeWithTransaction:transaction];
} error:nil];
}];
[actionSheet addAction:blockAction];
@ -2387,11 +2384,11 @@ typedef enum : NSUInteger {
editImmediately:YES];
// Delete the offers.
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
contactThread.hasDismissedOffers = YES;
[contactThread saveWithTransaction:transaction];
[interaction removeWithTransaction:transaction];
}];
} error:nil];
}
- (void)tappedAddToProfileWhitelistOfferMessage:(OWSContactOffersInteraction *)interaction
@ -2405,11 +2402,11 @@ typedef enum : NSUInteger {
[self presentAddThreadToProfileWhitelistWithSuccess:^() {
// Delete the offers.
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
contactThread.hasDismissedOffers = YES;
[contactThread saveWithTransaction:transaction];
[interaction removeWithTransaction:transaction];
}];
} error:nil];
}];
}
@ -2583,18 +2580,16 @@ typedef enum : NSUInteger {
success:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSAssertDebug(attachmentStreams.count == 1);
TSAttachmentStream *attachmentStream = attachmentStreams.firstObject;
[self.editingDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *postSuccessTransaction) {
[message setQuotedMessageThumbnailAttachmentStream:attachmentStream];
[message saveWithTransaction:postSuccessTransaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *postSuccessTransaction) {
[message setQuotedMessageThumbnailAttachmentStream:attachmentStream];
[message saveWithTransaction:postSuccessTransaction];
} error:nil];
}
failure:^(NSError *error) {
OWSLogWarn(@"Failed to redownload thumbnail with error: %@", error);
[self.editingDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *postSuccessTransaction) {
[message touchWithTransaction:postSuccessTransaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *postSuccessTransaction) {
[message touchWithTransaction:postSuccessTransaction];
} error:nil];
}];
}];
}
@ -2899,9 +2894,9 @@ typedef enum : NSUInteger {
if ([self.thread isKindOfClass:TSContactThread.class] && [message isKindOfClass:LKFriendRequestMessage.class]) {
NSString *recipientID = self.thread.contactIdentifier;
OWSAssertIsOnMainThread();
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKFriendRequestProtocol setFriendRequestStatusToSendingIfNeededForHexEncodedPublicKey:recipientID transaction:transaction];
}];
} error:nil];
}
}
@ -3716,7 +3711,7 @@ typedef enum : NSUInteger {
__block TSGroupThread *groupThread;
__block TSOutgoingMessage *message;
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
groupThread = [TSGroupThread getOrCreateThreadWithGroupModel:newGroupModel transaction:transaction];
NSString *updateGroupInfo =
@ -3730,7 +3725,7 @@ typedef enum : NSUInteger {
groupMetaMessage:TSGroupMetaMessageUpdate
expiresInSeconds:expiresInSeconds];
[message updateWithCustomMessage:updateGroupInfo transaction:transaction];
}];
} error:nil];
[groupThread fireAvatarChangedNotification];
@ -3800,7 +3795,7 @@ typedef enum : NSUInteger {
__block TSThread *thread = _thread;
__block NSString *currentDraft = [self.inputToolbar messageText];
[self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[thread setDraft:currentDraft transaction:transaction];
}];
}
@ -4501,17 +4496,17 @@ typedef enum : NSUInteger {
- (void)acceptFriendRequest:(TSIncomingMessage *)friendRequest
{
if (self.thread.isGroupThread || self.thread.contactIdentifier == nil) { return; }
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKFriendRequestProtocol acceptFriendRequestFromHexEncodedPublicKey:self.thread.contactIdentifier using:transaction];
}];
} error:nil];
}
- (void)declineFriendRequest:(TSIncomingMessage *)friendRequest
{
if (self.thread.isGroupThread || self.thread.contactIdentifier == nil) { return; }
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKFriendRequestProtocol declineFriendRequestFromHexEncodedPublicKey:self.thread.contactIdentifier using:transaction];
}];
} error:nil];
}
#pragma mark - ConversationViewLayoutDelegate
@ -4610,7 +4605,7 @@ typedef enum : NSUInteger {
[BenchManager completeEventWithEventId:@"fromSendUntil_toggleDefaultKeyboard"];
});
[self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.thread setDraft:@"" transaction:transaction];
}];
@ -5452,13 +5447,13 @@ typedef enum : NSUInteger {
}
dispatch_async(dispatch_get_main_queue(), ^{
__block TSInteraction *targetInteraction;
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.thread enumerateInteractionsWithTransaction:transaction usingBlock:^(TSInteraction *interaction, YapDatabaseReadTransaction *t) {
if (interaction.timestamp == timestamp.unsignedLongLongValue) {
targetInteraction = interaction;
}
}];
}];
} error:nil];
if (targetInteraction == nil || targetInteraction.interactionType != OWSInteractionType_OutgoingMessage) { return; }
NSString *hexEncodedPublicKey = targetInteraction.thread.contactIdentifier;
if (hexEncodedPublicKey == nil) { return; }

View file

@ -550,10 +550,9 @@ static const int kYapDatabaseRangeMaxLength = 25000;
if (oldIndicatorItem) {
// TODO ideally this would be happening within the *same* transaction that caused the unreadMessageIndicator
// to be cleared.
[self.editingDatabaseConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[oldIndicatorItem.interaction touchWithTransaction:transaction];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[oldIndicatorItem.interaction touchWithTransaction:transaction];
}];
}
if (self.hasClearedUnreadMessagesIndicator) {

View file

@ -889,7 +889,7 @@ public class ExperienceUpgradesPageViewController: OWSViewController, UIPageView
@objc public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
// Blocking write before dismiss, to be sure they're marked as complete
// before HomeView.didAppear is re-fired.
self.editingDBConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
Logger.info("marking all upgrades as seen.")
ExperienceUpgradeFinder.shared.markAllAsSeen(transaction: transaction)
}

View file

@ -1426,7 +1426,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
- (void)deleteThread:(TSThread *)thread
{
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
/* Loki: Orignal Code
=====================
if ([thread isKindOfClass:[TSGroupThread class]]) {
@ -1440,7 +1440,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
// Loki: For now hard delete all groups
[thread removeWithTransaction:transaction];
}];
} error:nil];
// Loki: Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:NSNotification.threadDeleted object:nil userInfo:@{ @"threadId": thread.uniqueId }];
@ -1457,7 +1457,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
TSThread *thread = [self threadForIndexPath:indexPath];
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
switch (self.homeViewMode) {
case HomeViewMode_Inbox:
[thread archiveThreadWithTransaction:transaction];
@ -1466,7 +1466,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[thread unarchiveThreadWithTransaction:transaction];
break;
}
}];
} error:nil];
[self updateViewState];
}

View file

@ -461,10 +461,9 @@ NS_ASSUME_NONNULL_BEGIN
TSGroupModel *model = [self makeGroup];
__block TSGroupThread *thread;
[OWSPrimaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
thread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
thread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction];
} error:nil];
OWSAssertDebug(thread);
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];

View file

@ -519,20 +519,19 @@ typedef void (^CustomLayoutBlock)(void);
- (void)verifyUnverifyButtonTapped:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateRecognized) {
[OWSPrimaryStorage.sharedManager.newDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
BOOL isVerified = [[OWSIdentityManager sharedManager] verificationStateForRecipientId:self.recipientId
transaction:transaction]
== OWSVerificationStateVerified;
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
BOOL isVerified = [[OWSIdentityManager sharedManager] verificationStateForRecipientId:self.recipientId
transaction:transaction]
== OWSVerificationStateVerified;
OWSVerificationState newVerificationState
= (isVerified ? OWSVerificationStateDefault : OWSVerificationStateVerified);
[[OWSIdentityManager sharedManager] setVerificationState:newVerificationState
identityKey:self.identityKey
recipientId:self.recipientId
isUserInitiatedChange:YES
transaction:transaction];
}];
OWSVerificationState newVerificationState
= (isVerified ? OWSVerificationStateDefault : OWSVerificationStateVerified);
[[OWSIdentityManager sharedManager] setVerificationState:newVerificationState
identityKey:self.identityKey
recipientId:self.recipientId
isUserInitiatedChange:YES
transaction:transaction];
} error:nil];
[self dismissViewControllerAnimated:YES completion:nil];
}

View file

@ -957,8 +957,14 @@ const CGFloat kIconViewLength = 24;
[stackView setLayoutMarginsRelativeArrangement:YES];
if (self.isGroupThread) {
profilePictureView.hexEncodedPublicKey = @"";
profilePictureView.isRSSFeed = true; // For now just always show the Session logo
TSGroupThread* groupThread = (TSGroupThread *)self.thread;
if (groupThread.isPublicChat && groupThread.groupModel.groupImage != nil && ![groupThread.groupModel.groupName isEqual:@"Loki Public Chat"]) {
profilePictureView.openGroupProfilePicture = groupThread.groupModel.groupImage;
profilePictureView.isRSSFeed = false;
} else {
profilePictureView.hexEncodedPublicKey = @"";
profilePictureView.isRSSFeed = true; // For now just always show the Session logo
}
} else {
profilePictureView.hexEncodedPublicKey = self.thread.contactIdentifier;
@ -1036,7 +1042,7 @@ const CGFloat kIconViewLength = 24;
}
if (self.disappearingMessagesConfiguration.dictionaryValueDidChange) {
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.disappearingMessagesConfiguration saveWithTransaction:transaction];
// MJK TODO - should be safe to remove this senderTimestamp
OWSDisappearingConfigurationUpdateInfoMessage *infoMessage =
@ -1053,7 +1059,7 @@ const CGFloat kIconViewLength = 24;
thread:self.thread];
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
} error:nil];
}
}
@ -1170,10 +1176,10 @@ const CGFloat kIconViewLength = 24;
TSOutgoingMessage *message =
[TSOutgoingMessage outgoingMessageInThread:gThread groupMetaMessage:TSGroupMetaMessageQuit expiresInSeconds:0];
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
[gThread leaveGroupWithTransaction:transaction];
}];
} error:nil];
[self.navigationController popViewControllerAnimated:YES];
}
@ -1389,9 +1395,9 @@ const CGFloat kIconViewLength = 24;
- (void)setThreadMutedUntilDate:(nullable NSDate *)value
{
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
[self.thread updateWithMutedUntilDate:value transaction:transaction];
}];
} error:nil];
[self updateTableContents];
}
@ -1456,9 +1462,9 @@ const CGFloat kIconViewLength = 24;
didPickConversationColor:(OWSConversationColor *_Nonnull)conversationColor
{
OWSLogDebug(@"picked color: %@", conversationColor.name);
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.thread updateConversationColorName:conversationColor.name transaction:transaction];
}];
} error:nil];
[self.contactsManager.avatarCache removeAllImages];
[self updateTableContents];

View file

@ -62,10 +62,9 @@ NS_ASSUME_NONNULL_BEGIN
animated:(BOOL)isAnimated
{
__block TSThread *thread = nil;
[OWSPrimaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
} error:nil];
[self presentConversationForThread:thread action:action animated:(BOOL)isAnimated];
}

View file

@ -867,10 +867,10 @@ NSError *OWSBackupErrorWithDescription(NSString *description)
return [AnyPromise promiseWithValue:error];
}
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// This should overwrite the attachment pointer with an attachment stream.
[stream saveWithTransaction:transaction];
}];
} error:nil];
return [AnyPromise promiseWithValue:@(1)];
}

View file

@ -864,9 +864,9 @@ NS_ASSUME_NONNULL_BEGIN
backupFragment.relativeFilePath = attachmentExport.relativeFilePath;
backupFragment.attachmentId = attachmentExport.attachmentId;
backupFragment.uncompressedDataLength = exportItem.uncompressedDataLength;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[backupFragment saveWithTransaction:transaction];
}];
} error:nil];
OWSLogVerbose(@"saved attachment: %@ as %@",
attachmentExport.attachmentFilePath,
@ -1102,7 +1102,7 @@ NS_ASSUME_NONNULL_BEGIN
// After every successful backup export, we can (and should) cull metadata
// for any backup fragment (i.e. CloudKit record) that wasn't involved in
// the latest backup export.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSArray<NSString *> *allRecordNames = [transaction allKeysInCollection:[OWSBackupFragment collection]];
NSMutableSet<NSString *> *obsoleteRecordNames = [NSMutableSet new];
@ -1110,7 +1110,7 @@ NS_ASSUME_NONNULL_BEGIN
[obsoleteRecordNames minusSet:activeRecordNames];
[transaction removeObjectsForKeys:obsoleteRecordNames.allObjects inCollection:[OWSBackupFragment collection]];
}];
} error:nil];
}
- (AnyPromise *)cleanUpCloudWithActiveRecordNames:(NSSet<NSString *> *)activeRecordNames

View file

@ -157,11 +157,11 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
[allItems addObjectsFromArray:self.attachmentsItems];
// Record metadata for all items, so that we can re-use them in incremental backups after the restore.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSBackupFragment *item in allItems) {
[item saveWithTransaction:transaction];
}
}];
} error:nil];
return [self downloadFilesFromCloud:blockingItems]
.thenInBackground(^{
@ -390,7 +390,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
}
__block NSUInteger count = 0;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSBackupFragment *item in self.attachmentsItems) {
if (self.isComplete) {
return;
@ -428,7 +428,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
@"Indicates that the backup import data is being restored.")
progress:@(count / (CGFloat)self.attachmentsItems.count)];
}
}];
} error:nil];
OWSLogError(@"enqueued lazy restore of %zd files.", count);
@ -456,7 +456,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
NSMutableDictionary<NSString *, NSNumber *> *restoredEntityCounts = [NSMutableDictionary new];
__block unsigned long long copiedEntities = 0;
__block BOOL aborted = NO;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *collection in collectionsToRestore) {
if ([collection isEqualToString:[OWSDatabaseMigration collection]]) {
// It's okay if there are existing migrations; we'll clear those
@ -585,7 +585,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
}
}
}
}];
} error:nil];
if (aborted) {
return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Backup import failed.")];

View file

@ -18,6 +18,7 @@
#import <SessionServiceKit/TSQuotedMessage.h>
#import <SessionServiceKit/TSThread.h>
#import <SessionServiceKit/YapDatabaseTransaction+OWS.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
#import <YapDatabase/YapDatabase.h>
NS_ASSUME_NONNULL_BEGIN
@ -525,14 +526,14 @@ typedef void (^OrphanDataBlock)(OWSOrphanData *);
success:^{
OWSLogInfo(@"Completed orphan data cleanup.");
[databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:AppVersion.sharedInstance.currentAppVersion
forKey:OWSOrphanDataCleaner_LastCleaningVersionKey
inCollection:OWSOrphanDataCleaner_Collection];
[transaction setDate:[NSDate new]
forKey:OWSOrphanDataCleaner_LastCleaningDateKey
inCollection:OWSOrphanDataCleaner_Collection];
}];
} error:nil];
if (completion) {
completion();
@ -613,7 +614,7 @@ typedef void (^OrphanDataBlock)(OWSOrphanData *);
NSDate *appLaunchTime = CurrentAppContext().appLaunchTime;
NSTimeInterval thresholdTimestamp = appLaunchTime.timeIntervalSince1970 - kMinimumOrphanAgeSeconds;
NSDate *thresholdDate = [NSDate dateWithTimeIntervalSince1970:thresholdTimestamp];
[databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSUInteger interactionsRemoved = 0;
for (NSString *interactionId in orphanData.interactionIds) {
if (!self.isMainAppAndActive) {
@ -674,7 +675,7 @@ typedef void (^OrphanDataBlock)(OWSOrphanData *);
[attachmentStream removeWithTransaction:transaction];
}
OWSLogInfo(@"Deleted orphan attachments: %zu", attachmentsRemoved);
}];
} error:nil];
if (shouldAbort) {
return nil;

View file

@ -596,16 +596,16 @@ typedef void (^DebugLogUploadFailure)(DebugLogUploader *uploader, NSError *error
DispatchMainThreadSafe(^{
__block TSThread *thread = nil;
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
}];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
} error:nil];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[ThreadUtil enqueueMessageWithText:url.absoluteString
inThread:thread
quotedReplyModel:nil
linkPreviewDraft:nil
transaction:transaction];
}];
} error:nil];
});
// Also copy to pasteboard.
@ -624,13 +624,13 @@ typedef void (^DebugLogUploadFailure)(DebugLogUploader *uploader, NSError *error
}];
DispatchMainThreadSafe(^{
if (thread) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[ThreadUtil enqueueMessageWithText:url.absoluteString
inThread:thread
quotedReplyModel:nil
linkPreviewDraft:nil
transaction:transaction];
}];
} error:nil];
} else {
[Pastelog showFailureAlertWithMessage:@"Could not find last thread."];
}

View file

@ -19,7 +19,7 @@ public class LK001UpdateFriendRequestStatusStorage : OWSDatabaseMigration {
private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) {
DispatchQueue.global().async {
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
var threads: [TSContactThread] = []
TSContactThread.enumerateCollectionObjects(with: transaction) { object, _ in
guard let thread = object as? TSContactThread else { return }

View file

@ -7,6 +7,7 @@ public final class ProfilePictureView : UIView {
@objc public var isRSSFeed = false
@objc public var hexEncodedPublicKey: String!
@objc public var additionalHexEncodedPublicKey: String?
@objc public var openGroupProfilePicture: UIImage?
// MARK: Components
private lazy var imageView = getImageView()
@ -43,6 +44,7 @@ public final class ProfilePictureView : UIView {
// MARK: Updating
@objc public func update() {
AssertIsOnMainThread()
func getProfilePicture(of size: CGFloat, for hexEncodedPublicKey: String) -> UIImage? {
guard !hexEncodedPublicKey.isEmpty else { return nil }
return OWSProfileManager.shared().profileAvatar(forRecipientId: hexEncodedPublicKey) ?? Identicon.generateIcon(string: hexEncodedPublicKey, size: size)
@ -61,8 +63,8 @@ public final class ProfilePictureView : UIView {
additionalImageView.isHidden = true
additionalImageView.image = nil
}
guard hexEncodedPublicKey != nil else { return } // Can happen in rare cases
imageView.image = isRSSFeed ? nil : getProfilePicture(of: size, for: hexEncodedPublicKey)
guard hexEncodedPublicKey != nil || openGroupProfilePicture != nil else { return }
imageView.image = isRSSFeed ? nil : (openGroupProfilePicture ?? getProfilePicture(of: size, for: hexEncodedPublicKey))
imageView.backgroundColor = isRSSFeed ? UIColor(rgbHex: 0x353535) : UIColor(rgbHex: 0xD8D8D8) // UIColor(rgbHex: 0xD8D8D8) = Colors.unimportant
imageView.layer.cornerRadius = size / 2
imageView.contentMode = isRSSFeed ? .center : .scaleAspectFit

View file

@ -341,9 +341,9 @@ NS_ASSUME_NONNULL_BEGIN
}
__block TSThread *thread = nil;
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:signalAccount.recipientId transaction:transaction];
}];
} error:nil];
OWSAssertDebug(thread);
[self.selectThreadViewDelegate threadWasSelected:thread];

View file

@ -375,23 +375,23 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
OWSAssertIsOnMainThread();
// TODO - in line with QuotedReply and other message attachments, saving should happen as part of sending
// preparation rather than duplicated here and in the SAE
[self.dbReadWriteConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
if (contactShare.avatarImage) {
[contactShare.dbRecord saveAvatarImage:contactShare.avatarImage transaction:transaction];
}
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
if (contactShare.avatarImage) {
[contactShare.dbRecord saveAvatarImage:contactShare.avatarImage transaction:transaction];
}
completionBlock:^{
__block TSOutgoingMessage *outgoingMessage = nil;
outgoingMessage = [ThreadUtil sendMessageNonDurablyWithContactShare:contactShare.dbRecord
inThread:self.thread
messageSender:self.messageSender
completion:^(NSError *_Nullable error) {
sendCompletion(error, outgoingMessage);
}];
// This is necessary to show progress.
self.outgoingMessage = outgoingMessage;
}];
}
completion:^{
__block TSOutgoingMessage *outgoingMessage = nil;
outgoingMessage = [ThreadUtil sendMessageNonDurablyWithContactShare:contactShare.dbRecord
inThread:self.thread
messageSender:self.messageSender
completion:^(NSError *_Nullable error) {
sendCompletion(error, outgoingMessage);
}];
// This is necessary to show progress.
self.outgoingMessage = outgoingMessage;
}];
}
@ -552,7 +552,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
OWSLogDebug(@"Confirming identity for recipient: %@", recipientId);
[self.dbReadWriteConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
OWSVerificationState verificationState =
[[OWSIdentityManager sharedManager] verificationStateForRecipientId:recipientId transaction:transaction];
switch (verificationState) {

View file

@ -340,7 +340,7 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
OWSAssertDebug(recipientIdsForIntersection.count > 0);
dispatch_async(self.serialQueue, ^{
[self.dbReadConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:recipientIdsForIntersection
forKey:OWSContactsManagerKeyLastKnownContactPhoneNumbers
inCollection:OWSContactsManagerCollection];
@ -354,7 +354,7 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
forKey:OWSContactsManagerKeyNextFullIntersectionDate
inCollection:OWSContactsManagerCollection];
}
}];
} error:nil];
});
}
@ -522,7 +522,7 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
}
// Update cached SignalAccounts on disk
[self.dbWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
OWSLogInfo(@"Saving %lu SignalAccounts", (unsigned long)accountsToSave.count);
for (SignalAccount *signalAccount in accountsToSave) {
OWSLogVerbose(@"Saving SignalAccount: %@", signalAccount);
@ -553,7 +553,7 @@ NSString *const OWSContactsManagerKeyNextFullIntersectionDate = @"OWSContactsMan
[signalAccounts sortUsingComparator:self.signalAccountComparator];
}
}
}];
} error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[self updateSignalAccounts:signalAccounts];

View file

@ -252,9 +252,9 @@ NSString *const kSyncManagerLastContactSyncKey = @"kTSStorageManagerOWSSyncManag
showTypingIndicators:showTypingIndicators
sendLinkPreviews:sendLinkPreviews];
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:syncConfigurationMessage transaction:transaction];
}];
} error:nil];
}
#pragma mark - Local Sync

View file

@ -292,9 +292,9 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob
- (void)setGlobalNotificationSound:(OWSSound)sound
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self setGlobalNotificationSound:sound transaction:transaction];
}];
} error:nil];
}
+ (void)setGlobalNotificationSound:(OWSSound)sound transaction:(YapDatabaseReadWriteTransaction *)transaction

View file

@ -156,10 +156,9 @@ NS_ASSUME_NONNULL_BEGIN
NSError *deleteError;
if ([fm removeItemAtPath:bloomFilterPath error:&deleteError]) {
OWSLogInfo(@"Successfully removed bloom filter cache.");
[OWSPrimaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeAllObjectsInCollection:@"TSRecipient"];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeAllObjectsInCollection:@"TSRecipient"];
} error:nil];
OWSLogInfo(@"Removed all TSRecipient records - will be replaced by SignalRecipients at next address sync.");
} else {
OWSLogError(@"Failed to remove bloom filter cache with error: %@", deleteError.localizedDescription);
@ -174,7 +173,7 @@ NS_ASSUME_NONNULL_BEGIN
// Versions less than or equal to 1.2.0 didn't store public chat mappings
+ (void)updatePublicChatMapping
{
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) {
for (LKPublicChat *chat in LKPublicChatAPI.defaultChats) {
TSGroupThread *thread = [TSGroupThread threadWithGroupId:[LKGroupUtilities getEncodedOpenGroupIDAsData:chat.id] transaction:transaction];
if (thread != nil) {
@ -203,7 +202,7 @@ NS_ASSUME_NONNULL_BEGIN
[thread saveWithTransaction:transaction];
}
}
}];
} error:nil];
}
@end

View file

@ -25,7 +25,7 @@ public class OWS110SortIdMigration: OWSDatabaseMigration {
private func doMigration(completion: @escaping OWSDatabaseMigrationCompletion) {
// TODO batch this?
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
var archivedThreads: [TSThread] = []

View file

@ -35,7 +35,7 @@ public class OWS111UDAttributesMigration: OWSDatabaseMigration {
private func doMigration() {
tsAccountManager.updateAccountAttributes().retainUntilComplete()
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
self.save(with: transaction)
}
}

View file

@ -39,7 +39,7 @@ public class OWS112TypingIndicatorsMigration: OWSDatabaseMigration {
self.typingIndicators.setTypingIndicatorsEnabled(value: false)
DispatchQueue.global().async {
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
self.save(with: transaction)
}

View file

@ -53,7 +53,7 @@ public class OWS113MultiAttachmentMediaMessages: OWSDatabaseMigration {
}
}
}
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
for (attachmentId, messageId) in legacyAttachments {
autoreleasepool {
guard let attachment = TSAttachment.fetch(uniqueId: attachmentId, transaction: transaction) else {

View file

@ -30,7 +30,7 @@ public class OWS114RemoveDynamicInteractions: OWSDatabaseMigration {
private func doMigrationAsync(completion : @escaping OWSDatabaseMigrationCompletion) {
DispatchQueue.global().async {
self.dbReadWriteConnection().readWrite { transaction in
try! Storage.writeSync { transaction in
guard let dbView = TSDatabaseView.threadSpecialMessagesDatabaseView(transaction) as? YapDatabaseViewTransaction else {
owsFailDebug("Couldn't load db view.")
return

View file

@ -5,6 +5,7 @@
#import "OWSDatabaseMigration.h"
#import <SessionServiceKit/OWSPrimaryStorage.h>
#import <SessionServiceKit/SSKEnvironment.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -70,16 +71,15 @@ NS_ASSUME_NONNULL_BEGIN
OWSDatabaseConnection *dbConnection = (OWSDatabaseConnection *)self.primaryStorage.newDatabaseConnection;
[dbConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self runUpWithTransaction:transaction];
}
completionBlock:^{
OWSLogInfo(@"Completed migration %@", self.uniqueId);
[self save];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self runUpWithTransaction:transaction];
}
completion:^{
OWSLogInfo(@"Completed migration %@", self.uniqueId);
[self save];
completion();
}];
completion();
}];
}
#pragma mark - Database Connections

View file

@ -78,7 +78,7 @@ NS_ASSUME_NONNULL_BEGIN
[knownMigrationIds addObject:migration.uniqueId];
}
[self.primaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSArray<NSString *> *savedMigrationIds = [transaction allKeysInCollection:OWSDatabaseMigration.collection];
NSMutableSet<NSString *> *unknownMigrationIds = [NSMutableSet new];
@ -89,7 +89,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSLogInfo(@"Culling unknown migration: %@", unknownMigrationId);
[transaction removeObjectForKey:unknownMigrationId inCollection:OWSDatabaseMigration.collection];
}
}];
} error:nil];
}
// Run migrations serially to:

View file

@ -5,6 +5,7 @@
#import "OWSResaveCollectionDBMigration.h"
#import <YapDatabase/YapDatabaseConnection.h>
#import <YapDatabase/YapDatabaseTransaction.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -20,18 +21,17 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(completion);
NSMutableArray<NSString *> *recordIds = [NSMutableArray new];
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[recordIds addObjectsFromArray:[transaction allKeysInCollection:collection]];
OWSLogInfo(@"Migrating %lu records from: %@.", (unsigned long)recordIds.count, collection);
}
completionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
completionBlock:^{
[self resaveBatch:recordIds
collection:collection
filter:filter
dbConnection:dbConnection
completion:completion];
}];
completion:^{
[self resaveBatch:recordIds
collection:collection
filter:filter
dbConnection:dbConnection
completion:completion];
}];
}
- (void)resaveBatch:(NSMutableArray<NSString *> *)recordIds
@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
const int kBatchSize = 1000;
for (int i = 0; i < kBatchSize && recordIds.count > 0; i++) {
NSString *messageId = [recordIds lastObject];
@ -65,14 +65,14 @@ NS_ASSUME_NONNULL_BEGIN
[entity saveWithTransaction:transaction];
}
}
completionBlock:^{
// Process the next batch.
[self resaveBatch:recordIds
collection:collection
filter:filter
dbConnection:dbConnection
completion:completion];
}];
completion:^{
// Process the next batch.
[self resaveBatch:recordIds
collection:collection
filter:filter
dbConnection:dbConnection
completion:completion];
}];
}
@end

View file

@ -31,6 +31,7 @@
#import <SessionServiceKit/TSYapDatabaseObject.h>
#import <SessionServiceKit/UIImage+OWS.h>
#import <SessionServiceKit/YapDatabaseConnection+OWS.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -238,7 +239,8 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
// Ensure that the success and failure blocks are called on the main thread.
void (^failureBlock)(NSError *) = ^(NSError *error) {
OWSLogError(@"Updating service with profile failed.");
/*
// We use a "self-only" contact sync to indicate to desktop
// that we've changed our profile and that it should do a
// profile fetch for "self".
@ -248,6 +250,10 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
if (requiresSync) {
[[self.syncManager syncLocalContact] retainUntilComplete];
}
*/
if (requiresSync) {
[LKSyncMessagesProtocol syncProfile];
}
dispatch_async(dispatch_get_main_queue(), ^{
failureBlockParameter(error);
@ -255,13 +261,18 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
};
void (^successBlock)(void) = ^{
OWSLogInfo(@"Successfully updated service with profile.");
/*
// We use a "self-only" contact sync to indicate to desktop
// that we've changed our profile and that it should do a
// profile fetch for "self".
if (requiresSync) {
[[self.syncManager syncLocalContact] retainUntilComplete];
}
*/
if (requiresSync) {
[LKSyncMessagesProtocol syncProfile];
}
dispatch_async(dispatch_get_main_queue(), ^{
successBlockParameter();
@ -695,7 +706,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
// Remove blocked users and groups from profile whitelist.
//
// This will always succeed.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectsForKeys:intersectingRecipientIds.allObjects
inCollection:kOWSProfileManager_UserWhitelistCollection];
for (NSData *groupId in intersectingGroupIds) {
@ -703,7 +714,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
[transaction removeObjectForKey:groupIdKey
inCollection:kOWSProfileManager_GroupWhitelistCollection];
}
}];
} error:nil];
return @(1);
});
@ -750,7 +761,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
{
OWSLogWarn(@"Clearing the profile whitelist.");
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:kOWSProfileManager_UserWhitelistCollection];
[transaction removeAllObjectsInCollection:kOWSProfileManager_GroupWhitelistCollection];
OWSAssertDebug(0 == [transaction numberOfKeysInCollection:kOWSProfileManager_UserWhitelistCollection]);
@ -795,7 +806,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
OWSAssertDebug(recipientIds);
NSMutableSet<NSString *> *newRecipientIds = [NSMutableSet new];
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *recipientId in recipientIds) {
NSNumber *_Nullable oldValue =
[transaction objectForKey:recipientId inCollection:kOWSProfileManager_UserWhitelistCollection];
@ -813,16 +824,16 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
[newRecipientIds addObject:recipientId];
}
}
completionBlock:^{
for (NSString *recipientId in newRecipientIds) {
[[NSNotificationCenter defaultCenter]
postNotificationNameAsync:kNSNotificationName_ProfileWhitelistDidChange
object:nil
userInfo:@{
kNSNotificationKey_ProfileRecipientId : recipientId,
}];
}
}];
completion:^{
for (NSString *recipientId in newRecipientIds) {
[[NSNotificationCenter defaultCenter]
postNotificationNameAsync:kNSNotificationName_ProfileWhitelistDidChange
object:nil
userInfo:@{
kNSNotificationKey_ProfileRecipientId : recipientId,
}];
}
}];
}
- (BOOL)isUserInProfileWhitelist:(NSString *)recipientId
@ -849,7 +860,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
NSString *groupIdKey = [self groupKeyForGroupId:groupId];
__block BOOL didChange = NO;
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSNumber *_Nullable oldValue =
[transaction objectForKey:groupIdKey inCollection:kOWSProfileManager_GroupWhitelistCollection];
if (oldValue && oldValue.boolValue) {
@ -859,16 +870,16 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
didChange = YES;
}
}
completionBlock:^{
if (didChange) {
[[NSNotificationCenter defaultCenter]
postNotificationNameAsync:kNSNotificationName_ProfileWhitelistDidChange
object:nil
userInfo:@{
kNSNotificationKey_ProfileGroupId : groupId,
}];
}
}];
completion:^{
if (didChange) {
[[NSNotificationCenter defaultCenter]
postNotificationNameAsync:kNSNotificationName_ProfileWhitelistDidChange
object:nil
userInfo:@{
kNSNotificationKey_ProfileGroupId : groupId,
}];
}
}];
}
- (void)addThreadToProfileWhitelist:(TSThread *)thread
@ -1451,9 +1462,9 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
[[OWSProfileKeyMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
} error:nil];
}
#pragma mark - Notifications

View file

@ -55,9 +55,9 @@ NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId";
dbConnection:(YapDatabaseConnection *)dbConnection
{
__block OWSUserProfile *userProfile;
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
userProfile = [OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId transaction:transaction];
}];
} error:nil];
return userProfile;
}
@ -187,9 +187,9 @@ NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId";
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChanges:changeBlock functionName:functionName transaction:transaction completion:completion];
}];
} error:nil];
}
- (void)applyChanges:(void (^)(id))changeBlock
@ -369,9 +369,9 @@ NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId";
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithProfileKey:profileKey transaction:transaction completion:completion];
}];
} error:nil];
}
- (void)updateWithProfileKey:(OWSAES256Key *)profileKey

View file

@ -11,6 +11,7 @@
#import <SessionServiceKit/TSStorageHeaders.h>
#import <SessionServiceKit/YapDatabaseConnection+OWS.h>
#import <SessionServiceKit/YapDatabaseTransaction+OWS.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -87,9 +88,9 @@ NSString *const OWSPreferencesKeySystemCallLogEnabled = @"OWSPreferencesKeySyste
- (void)setValueForKey:(NSString *)key toValue:(nullable id)value
{
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self setValueForKey:key toValue:value transaction:transaction];
}];
} error:nil];
}
- (void)setValueForKey:(NSString *)key

View file

@ -26,6 +26,7 @@
#import <SessionServiceKit/TSInvalidIdentityKeyErrorMessage.h>
#import <SessionServiceKit/TSOutgoingMessage.h>
#import <SessionServiceKit/TSThread.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -87,7 +88,7 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess
+ (void)enqueueDeviceLinkMessage:(LKDeviceLinkMessage *)message
{
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
}
@ -203,25 +204,23 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess
block:^(void (^benchmarkCompletion)(void)) {
// To avoid blocking the send flow, we dispatch an async write from within this read
// transaction
[self.dbConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull writeTransaction) {
[message saveWithTransaction:writeTransaction];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull writeTransaction) {
[message saveWithTransaction:writeTransaction];
OWSLinkPreview *_Nullable linkPreview =
[self linkPreviewForLinkPreviewDraft:linkPreviewDraft
transaction:writeTransaction];
if (linkPreview) {
[message updateWithLinkPreview:linkPreview transaction:writeTransaction];
}
NSMutableArray<OWSOutgoingAttachmentInfo *> *attachmentInfos = [NSMutableArray new];
for (SignalAttachment *attachment in attachments) {
OWSOutgoingAttachmentInfo *attachmentInfo = [attachment buildOutgoingAttachmentInfoWithMessage:message];
[attachmentInfos addObject:attachmentInfo];
}
completionBlock(message, attachmentInfos, writeTransaction);
OWSLinkPreview *_Nullable linkPreview =
[self linkPreviewForLinkPreviewDraft:linkPreviewDraft
transaction:writeTransaction];
if (linkPreview) {
[message updateWithLinkPreview:linkPreview transaction:writeTransaction];
}
completionBlock:benchmarkCompletion];
NSMutableArray<OWSOutgoingAttachmentInfo *> *attachmentInfos = [NSMutableArray new];
for (SignalAttachment *attachment in attachments) {
OWSOutgoingAttachmentInfo *attachmentInfo = [attachment buildOutgoingAttachmentInfoWithMessage:message];
[attachmentInfos addObject:attachmentInfo];
}
completionBlock(message, attachmentInfos, writeTransaction);
} completion:benchmarkCompletion];
}];
return message;
@ -251,7 +250,7 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess
contactShare:contactShare
linkPreview:nil];
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[message saveWithTransaction:transaction];
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
@ -266,7 +265,7 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess
TSOutgoingMessage *message =
[TSOutgoingMessage outgoingMessageInThread:thread groupMetaMessage:TSGroupMetaMessageQuit expiresInSeconds:0];
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
}
@ -701,25 +700,24 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess
{
OWSLogInfo(@"");
[OWSPrimaryStorage.sharedManager.newDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self removeAllObjectsInCollection:[TSThread collection]
class:[TSThread class]
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self removeAllObjectsInCollection:[TSThread collection]
class:[TSThread class]
transaction:transaction];
[self removeAllObjectsInCollection:[TSInteraction collection]
class:[TSInteraction class]
transaction:transaction];
[self removeAllObjectsInCollection:[TSAttachment collection]
class:[TSAttachment class]
transaction:transaction];
@try {
[self removeAllObjectsInCollection:[SignalRecipient collection]
class:[SignalRecipient class]
transaction:transaction];
[self removeAllObjectsInCollection:[TSInteraction collection]
class:[TSInteraction class]
transaction:transaction];
[self removeAllObjectsInCollection:[TSAttachment collection]
class:[TSAttachment class]
transaction:transaction];
@try {
[self removeAllObjectsInCollection:[SignalRecipient collection]
class:[SignalRecipient class]
transaction:transaction];
} @catch (NSException *exception) {
// Do nothing
}
}];
} @catch (NSException *exception) {
// Do nothing
}
} error:nil];
[TSAttachmentStream deleteAttachments];
}

View file

@ -251,9 +251,9 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
- (uint32_t)getOrGenerateRegistrationId
{
__block uint32_t result;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
result = [self getOrGenerateRegistrationId:transaction];
}];
} error:nil];
return result;
}
@ -523,11 +523,11 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
- (void)storeServerAuthToken:(NSString *)authToken
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:authToken
forKey:TSAccountManager_ServerAuthToken
inCollection:TSAccountManager_UserAccountCollection];
}];
} error:nil];
}
+ (void)unregisterTextSecureWithSuccess:(void (^)(void))success failure:(void (^)(NSError *error))failureBlock
@ -599,7 +599,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
self.cachedIsDeregistered = @(isDeregistered);
}
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:@(isDeregistered)
forKey:TSAccountManager_IsDeregisteredKey
inCollection:TSAccountManager_UserAccountCollection];
@ -623,7 +623,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
_cachedLocalNumber = nil;
_phoneNumberAwaitingVerification = nil;
_cachedIsDeregistered = nil;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection];
[[OWSPrimaryStorage sharedManager] resetSessionStore:transaction];
@ -631,7 +631,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
[transaction setObject:localNumber
forKey:TSAccountManager_ReregisteringPhoneNumberKey
inCollection:TSAccountManager_UserAccountCollection];
}];
} error:nil];
[self postRegistrationStateDidChangeNotification];
@ -723,7 +723,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
}
AnyPromise *promise = [self performUpdateAccountAttributes];
promise = promise.then(^(id value) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Clear the update request unless a new update has been requested
// while this update was in flight.
NSDate *_Nullable latestUpdateRequestDate =
@ -733,7 +733,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
[transaction removeObjectForKey:TSAccountManager_NeedsAccountAttributesUpdateKey
inCollection:TSAccountManager_UserAccountCollection];
}
}];
} error:nil];
});
return promise;
}

View file

@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN
NSSet<NSString *> *registeredRecipientIds = operation.registeredRecipientIds;
NSMutableSet<SignalRecipient *> *recipients = [NSMutableSet new];
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *recipientId in recipientIdsToLookup) {
if ([registeredRecipientIds containsObject:recipientId]) {
SignalRecipient *recipient =
@ -106,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN
[SignalRecipient markRecipientAsUnregistered:recipientId transaction:transaction];
}
}
}];
} error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
success([recipients copy]);

View file

@ -53,9 +53,9 @@ NSString *const TSContactThreadPrefix = @"c";
OWSAssertDebug(contactId.length > 0);
__block TSContactThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithContactId:contactId transaction:transaction];
}];
} error:nil];
return thread;
}

View file

@ -89,9 +89,9 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific
OWSAssertDebug(groupId.length > 0);
__block TSGroupThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithGroupId:groupId groupType:groupType transaction:transaction];
}];
} error:nil];
return thread;
}
@ -117,9 +117,9 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific
OWSAssertDebug(groupModel.groupId.length > 0);
__block TSGroupThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
}];
} error:nil];
return thread;
}
@ -242,9 +242,9 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific
- (void)leaveGroupWithSneakyTransaction
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self leaveGroupWithTransaction:transaction];
}];
} error:nil];
}
- (void)leaveGroupWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
@ -272,9 +272,9 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific
- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateAvatarWithAttachmentStream:attachmentStream transaction:transaction];
}];
} error:nil];
}
- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream

View file

@ -66,23 +66,21 @@ NSString *const kOWSPrimaryStorage_MayHaveLinkedDevices = @"kTSStorageManager_Ma
- (void)clearMayHaveLinkedDevices
{
// Note that we write async to avoid opening transactions within transactions.
[OWSPrimaryStorage.sharedManager.newDatabaseConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction setObject:@(NO)
forKey:kOWSPrimaryStorage_MayHaveLinkedDevices
inCollection:kOWSPrimaryStorage_OWSDeviceCollection];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction setObject:@(NO)
forKey:kOWSPrimaryStorage_MayHaveLinkedDevices
inCollection:kOWSPrimaryStorage_OWSDeviceCollection];
}];
}
- (void)setMayHaveLinkedDevices
{
// Note that we write async to avoid opening transactions within transactions.
[OWSPrimaryStorage.sharedManager.newDatabaseConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction setObject:@(YES)
forKey:kOWSPrimaryStorage_MayHaveLinkedDevices
inCollection:kOWSPrimaryStorage_OWSDeviceCollection];
}];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction setObject:@(YES)
forKey:kOWSPrimaryStorage_MayHaveLinkedDevices
inCollection:kOWSPrimaryStorage_OWSDeviceCollection];
}];
}
- (BOOL)hasReceivedSyncMessageInLastSeconds:(NSTimeInterval)intervalSeconds

View file

@ -130,14 +130,13 @@ NS_ASSUME_NONNULL_BEGIN
success:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSAssertDebug(attachmentStreams.count == 1);
TSAttachmentStream *attachmentStream = attachmentStreams.firstObject;
[self.primaryStorage.newDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[outgoingMessage setQuotedMessageThumbnailAttachmentStream:attachmentStream];
[outgoingMessage saveWithTransaction:transaction];
if (serverID != 0) {
[OWSPrimaryStorage.sharedManager setIDForMessageWithServerID:serverID to:outgoingMessage.uniqueId in:transaction];
}
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[outgoingMessage setQuotedMessageThumbnailAttachmentStream:attachmentStream];
[outgoingMessage saveWithTransaction:transaction];
if (serverID != 0) {
[OWSPrimaryStorage.sharedManager setIDForMessageWithServerID:serverID to:outgoingMessage.uniqueId in:transaction];
}
} error:nil];
}
failure:^(NSError *error) {
OWSLogWarn(@"failed to fetch thumbnail for transcript: %lu with error: %@",

View file

@ -53,12 +53,9 @@ public extension LokiAPI {
}
}.done(on: DispatchQueue.global()) { snode in
seal.fulfill(snode)
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
print("[Loki] Persisting snode pool to database.")
storage.setSnodePool(LokiAPI.snodePool, in: transaction)
}
try! Storage.writeSync { transaction in
print("[Loki] Persisting snode pool to database.")
storage.setSnodePool(LokiAPI.snodePool, in: transaction)
}
}.catch(on: DispatchQueue.global()) { error in
print("[Loki] Failed to contact seed node at: \(target).")
@ -90,12 +87,8 @@ public extension LokiAPI {
parseTargets(from: $0)
}.get { swarm in
swarmCache[hexEncodedPublicKey] = swarm
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
storage.setSwarm(swarm, for: hexEncodedPublicKey, in: transaction)
}
try! Storage.writeSync { transaction in
storage.setSwarm(swarm, for: hexEncodedPublicKey, in: transaction)
}
}
}
@ -108,12 +101,8 @@ public extension LokiAPI {
internal static func dropSnodeFromSnodePool(_ target: LokiAPITarget) {
LokiAPI.snodePool.remove(target)
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
storage.dropSnodeFromSnodePool(target, in: transaction)
}
try! Storage.writeSync { transaction in
storage.dropSnodeFromSnodePool(target, in: transaction)
}
}
@ -122,12 +111,8 @@ public extension LokiAPI {
if var swarm = swarm, let index = swarm.firstIndex(of: target) {
swarm.remove(at: index)
LokiAPI.swarmCache[hexEncodedPublicKey] = swarm
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
storage.setSwarm(swarm, for: hexEncodedPublicKey, in: transaction)
}
try! Storage.writeSync { transaction in
storage.setSwarm(swarm, for: hexEncodedPublicKey, in: transaction)
}
}
}
@ -135,11 +120,8 @@ public extension LokiAPI {
// MARK: Public API
@objc public static func clearSnodePool() {
snodePool.removeAll()
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
storage.clearSnodePool(in: transaction)
}
try! Storage.writeSync { transaction in
storage.clearSnodePool(in: transaction)
}
}

View file

@ -194,14 +194,14 @@ public final class LokiAPI : NSObject {
var result: String? = nil
// Uses a read/write connection because getting the last message hash value also removes expired messages as needed
// TODO: This shouldn't be the case; a getter shouldn't have an unexpected side effect
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
result = storage.getLastMessageHash(forSnode: target.address, transaction: transaction)
}
return result
}
private static func setLastMessageHashValue(for target: LokiAPITarget, hashValue: String, expirationDate: UInt64) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
storage.setLastMessageHash(forSnode: target.address, hash: hashValue, expiresAt: expirationDate, transaction: transaction)
}
}
@ -218,7 +218,7 @@ public final class LokiAPI : NSObject {
}
private static func setReceivedMessageHashValues(to receivedMessageHashValues: Set<String>) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.setObject(receivedMessageHashValues, forKey: receivedMessageHashValuesKey, inCollection: receivedMessageHashValuesCollection)
}
}

View file

@ -38,11 +38,8 @@ public class LokiDotNetAPI : NSObject {
return Promise.value(token)
} else {
return requestNewAuthToken(for: server).then(on: DispatchQueue.global()) { submitAuthToken($0, for: server) }.map(on: DispatchQueue.global()) { token in
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
setAuthToken(for: server, to: token, in: transaction)
}
try! Storage.writeSync { transaction in
setAuthToken(for: server, to: token, in: transaction)
}
return token
}
@ -54,11 +51,8 @@ public class LokiDotNetAPI : NSObject {
}
public static func clearAuthToken(for server: String) {
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
transaction.removeObject(forKey: server, inCollection: authTokenCollection)
}
try! Storage.writeSync { transaction in
transaction.removeObject(forKey: server, inCollection: authTokenCollection)
}
}

View file

@ -81,15 +81,7 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
}
})
}.map(on: DispatchQueue.global()) { deviceLinks in
storage.cacheDeviceLinks(deviceLinks)
/*
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
storage.setDeviceLinks(deviceLinks, in: transaction)
}
}
*/
storage.setDeviceLinks(deviceLinks)
return deviceLinks
}
}.handlingInvalidAuthTokenIfNeeded(for: server)
@ -122,16 +114,8 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
deviceLinks = storage.getDeviceLinks(for: getUserHexEncodedPublicKey(), in: transaction)
}
deviceLinks.insert(deviceLink)
return setDeviceLinks(deviceLinks).then(on: LokiAPI.workQueue) { _ -> Promise<Void> in
let (promise, seal) = Promise<Void>.pending()
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
storage.addDeviceLink(deviceLink, in: transaction)
}
seal.fulfill(())
}
return promise
return setDeviceLinks(deviceLinks).map(on: LokiAPI.workQueue) { _ in
storage.addDeviceLink(deviceLink)
}
}
@ -142,16 +126,8 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
deviceLinks = storage.getDeviceLinks(for: getUserHexEncodedPublicKey(), in: transaction)
}
deviceLinks.remove(deviceLink)
return setDeviceLinks(deviceLinks).then(on: LokiAPI.workQueue) { _ -> Promise<Void> in
let (promise, seal) = Promise<Void>.pending()
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
storage.removeDeviceLink(deviceLink, in: transaction)
}
seal.fulfill(())
}
return promise
return setDeviceLinks(deviceLinks).map(on: LokiAPI.workQueue) { _ in
storage.removeDeviceLink(deviceLink)
}
}

View file

@ -123,13 +123,11 @@ public enum OnionRequestAPI {
}
}.map(on: LokiAPI.workQueue) { paths in
OnionRequestAPI.paths = paths
// Dispatch async on the main queue to avoid nested write transactions
try! Storage.writeSync { transaction in
print("[Loki] Persisting onion request paths to database.")
OWSPrimaryStorage.shared().setOnionRequestPaths(paths, in: transaction)
}
DispatchQueue.main.async {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
print("[Loki] Persisting onion request paths to database.")
storage.setOnionRequestPaths(paths, in: transaction)
}
NotificationCenter.default.post(name: .pathsBuilt, object: nil)
}
return paths
@ -165,12 +163,8 @@ public enum OnionRequestAPI {
private static func dropAllPaths() {
paths.removeAll()
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
storage.clearOnionRequestPaths(in: transaction)
}
try! Storage.writeSync { transaction in
OWSPrimaryStorage.shared().clearOnionRequestPaths(in: transaction)
}
}

View file

@ -19,7 +19,8 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
// MARK: Convenience
private static var userDisplayName: String {
return SSKEnvironment.shared.contactsManager.displayName(forPhoneIdentifier: getUserHexEncodedPublicKey()) ?? "Anonymous"
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
return SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userPublicKey) ?? "Anonymous"
}
// MARK: Database
@ -37,13 +38,13 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
}
private static func setLastMessageServerID(for group: UInt64, on server: String, to newValue: UInt64) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.setObject(newValue, forKey: "\(server).\(group)", inCollection: lastMessageServerIDCollection)
}
}
private static func removeLastMessageServerID(for group: UInt64, on server: String) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.removeObject(forKey: "\(server).\(group)", inCollection: lastMessageServerIDCollection)
}
}
@ -57,13 +58,13 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
}
private static func setLastDeletionServerID(for group: UInt64, on server: String, to newValue: UInt64) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.setObject(newValue, forKey: "\(server).\(group)", inCollection: lastDeletionServerIDCollection)
}
}
private static func removeLastDeletionServerID(for group: UInt64, on server: String) {
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.removeObject(forKey: "\(server).\(group)", inCollection: lastDeletionServerIDCollection)
}
}
@ -271,7 +272,7 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
print("[Loki] Couldn't parse display names for users: \(hexEncodedPublicKeys) from: \(rawResponse).")
throw LokiDotNetAPIError.parsingFailed
}
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
data.forEach { data in
guard let user = data["user"] as? JSON, let hexEncodedPublicKey = user["username"] as? String, let rawDisplayName = user["name"] as? String else { return }
let endIndex = hexEncodedPublicKey.endIndex
@ -330,6 +331,51 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
}
}
static func updateProfileIfNeeded(for channel: UInt64, on server: String, from info: LokiPublicChatInfo) {
let storage = OWSPrimaryStorage.shared()
let publicChatID = "\(server).\(channel)"
try! Storage.writeSync { transaction in
// Update user count
storage.setUserCount(info.memberCount, forPublicChatWithID: publicChatID, in: transaction)
let groupThread = TSGroupThread.getOrCreateThread(withGroupId: publicChatID.data(using: .utf8)!, groupType: .openGroup, transaction: transaction)
// Update display name if needed
let groupModel = groupThread.groupModel
if groupModel.groupName != info.displayName {
let newGroupModel = TSGroupModel(title: info.displayName, memberIds: groupModel.groupMemberIds, image: groupModel.groupImage, groupId: groupModel.groupId, groupType: groupModel.groupType, adminIds: groupModel.groupAdminIds)
groupThread.groupModel = newGroupModel
groupThread.save(with: transaction)
}
// Download and update profile picture if needed
let oldProfilePictureURL = storage.getProfilePictureURL(forPublicChatWithID: publicChatID, in: transaction)
if oldProfilePictureURL != info.profilePictureURL || groupModel.groupImage == nil {
storage.setProfilePictureURL(info.profilePictureURL, forPublicChatWithID: publicChatID, in: transaction)
if let avatarURL = info.profilePictureURL {
let configuration = URLSessionConfiguration.default
let manager = AFURLSessionManager.init(sessionConfiguration: configuration)
let url = URL(string: "\(server)\(avatarURL)")!
let request = URLRequest(url: url)
let task = manager.downloadTask(with: request, progress: nil,
destination: { (targetPath: URL, response: URLResponse) -> URL in
let tempFilePath = URL(fileURLWithPath: OWSTemporaryDirectoryAccessibleAfterFirstAuth()).appendingPathComponent(UUID().uuidString)
return tempFilePath
},
completionHandler: { (response: URLResponse, filePath: URL?, error: Error?) in
if let error = error {
print("[Loki] Couldn't download profile picture for public chat channel with ID: \(channel) on server: \(server).")
return
}
if let filePath = filePath, let avatarData = try? Data.init(contentsOf: filePath) {
let attachmentStream = TSAttachmentStream(contentType: OWSMimeTypeImageJpeg, byteCount: UInt32(avatarData.count), sourceFilename: nil, caption: nil, albumMessageId: nil)
try! attachmentStream.write(avatarData)
groupThread.updateAvatar(with: attachmentStream)
}
})
task.resume()
}
}
}
}
// MARK: Joining & Leaving
@objc(getInfoForChannelWithID:onServer:)
public static func objc_getInfo(for channel: UInt64, on server: String) -> AnyPromise {
@ -349,17 +395,19 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
let annotation = annotations.first,
let info = annotation["value"] as? JSON,
let displayName = info["name"] as? String,
let profilePictureURL = info["avatar"] as? String,
let countInfo = data["counts"] as? JSON,
let memberCount = countInfo["subscribers"] as? Int else {
print("[Loki] Couldn't parse info for public chat channel with ID: \(channel) on server: \(server) from: \(rawResponse).")
throw LokiDotNetAPIError.parsingFailed
}
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
storage.setUserCount(memberCount, forPublicChatWithID: "\(server).\(channel)", in: transaction)
}
// TODO: Use this to update open group names as needed
return LokiPublicChatInfo(displayName: displayName, memberCount: memberCount)
let publicChatInfo = LokiPublicChatInfo(displayName: displayName, profilePictureURL: profilePictureURL, memberCount: memberCount)
updateProfileIfNeeded(for: channel, on: server, from: publicChatInfo)
return publicChatInfo
}
}.handlingInvalidAuthTokenIfNeeded(for: server)
}

View file

@ -1,5 +1,6 @@
public struct LokiPublicChatInfo {
public let displayName: String
public let profilePictureURL: String?
public let memberCount: Int
}

View file

@ -71,7 +71,7 @@ public final class LokiPublicChatManager : NSObject {
let model = TSGroupModel(title: chat.displayName, memberIds: [userHexEncodedPublicKey!, chat.server], image: nil, groupId: LKGroupUtilities.getEncodedOpenGroupIDAsData(chat.id), groupType: .openGroup, adminIds: [])
// Store the group chat mapping
self.storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
let thread = TSGroupThread.getOrCreateThread(with: model, transaction: transaction)
// Save the group chat
@ -118,7 +118,7 @@ public final class LokiPublicChatManager : NSObject {
}
// Remove the chat from the db
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
LokiDatabaseUtilities.removePublicChat(for: threadId, in: transaction)
}

View file

@ -150,6 +150,9 @@ public final class LokiPublicChatPoller : NSObject {
if !wasSentByCurrentUser {
content.setDataMessage(try! dataMessage.build())
} else {
// The line below is necessary to make it so that when a user sends a message in an open group and then
// deletes and re-joins the open group without closing the app in between, the message isn't ignored.
SyncMessagesProtocol.dropFromSyncMessageTimestampCache(message.timestamp, for: senderHexEncodedPublicKey)
let syncMessageSentBuilder = SSKProtoSyncMessageSent.builder()
syncMessageSentBuilder.setMessage(try! dataMessage.build())
syncMessageSentBuilder.setDestination(userHexEncodedPublicKey)
@ -163,7 +166,7 @@ public final class LokiPublicChatPoller : NSObject {
envelope.setSource(senderHexEncodedPublicKey)
envelope.setSourceDevice(OWSDevicePrimaryDeviceId)
envelope.setContent(try! content.build().serializedData())
storage.dbReadWriteConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
transaction.setObject(senderDisplayName, forKey: senderHexEncodedPublicKey, inCollection: publicChat.id)
let messageServerID = message.serverID
SSKEnvironment.shared.messageManager.throws_processEnvelope(try! envelope.build(), plaintextData: try! content.build().serializedData(), wasReceivedByUD: false, transaction: transaction, serverID: messageServerID ?? 0)
@ -213,9 +216,8 @@ public final class LokiPublicChatPoller : NSObject {
private func pollForDeletedMessages() {
let publicChat = self.publicChat
let _ = LokiPublicChatAPI.getDeletedMessageServerIDs(for: publicChat.channel, on: publicChat.server).done(on: DispatchQueue.global()) { deletedMessageServerIDs in
let storage = OWSPrimaryStorage.shared()
storage.dbReadWriteConnection.readWrite { transaction in
let deletedMessageIDs = deletedMessageServerIDs.compactMap { storage.getIDForMessage(withServerID: UInt($0), in: transaction) }
try! Storage.writeSync { transaction in
let deletedMessageIDs = deletedMessageServerIDs.compactMap { OWSPrimaryStorage.shared().getIDForMessage(withServerID: UInt($0), in: transaction) }
deletedMessageIDs.forEach { messageID in
TSMessage.fetch(uniqueId: messageID)?.remove(with: transaction)
}

View file

@ -4,22 +4,20 @@
public extension OWSPrimaryStorage {
// MARK: - Snode Pool
private static let snodePoolCollection = "LokiSnodePoolCollection"
public func setSnodePool(_ snodePool: Set<LokiAPITarget>, in transaction: YapDatabaseReadWriteTransaction) {
clearSnodePool(in: transaction)
snodePool.forEach { snode in
transaction.setObject(snode, forKey: snode.description, inCollection: OWSPrimaryStorage.snodePoolCollection)
transaction.setObject(snode, forKey: snode.description, inCollection: Storage.snodePoolCollection)
}
}
public func clearSnodePool(in transaction: YapDatabaseReadWriteTransaction) {
transaction.removeAllObjects(inCollection: OWSPrimaryStorage.snodePoolCollection)
transaction.removeAllObjects(inCollection: Storage.snodePoolCollection)
}
public func getSnodePool(in transaction: YapDatabaseReadTransaction) -> Set<LokiAPITarget> {
var result: Set<LokiAPITarget> = []
transaction.enumerateKeysAndObjects(inCollection: OWSPrimaryStorage.snodePoolCollection) { _, object, _ in
transaction.enumerateKeysAndObjects(inCollection: Storage.snodePoolCollection) { _, object, _ in
guard let snode = object as? LokiAPITarget else { return }
result.insert(snode)
}
@ -27,33 +25,29 @@ public extension OWSPrimaryStorage {
}
public func dropSnodeFromSnodePool(_ snode: LokiAPITarget, in transaction: YapDatabaseReadWriteTransaction) {
transaction.removeObject(forKey: snode.description, inCollection: OWSPrimaryStorage.snodePoolCollection)
transaction.removeObject(forKey: snode.description, inCollection: Storage.snodePoolCollection)
}
// MARK: - Swarm
private func getSwarmCollection(for publicKey: String) -> String {
return "LokiSwarmCollection-\(publicKey)"
}
public func setSwarm(_ swarm: [Snode], for publicKey: String, in transaction: YapDatabaseReadWriteTransaction) {
print("[Loki] Caching swarm for: \(publicKey).")
clearSwarm(for: publicKey, in: transaction)
let collection = getSwarmCollection(for: publicKey)
let collection = Storage.getSwarmCollection(for: publicKey)
swarm.forEach { snode in
transaction.setObject(snode, forKey: snode.description, inCollection: collection)
}
}
public func clearSwarm(for publicKey: String, in transaction: YapDatabaseReadWriteTransaction) {
let collection = getSwarmCollection(for: publicKey)
let collection = Storage.getSwarmCollection(for: publicKey)
transaction.removeAllObjects(inCollection: collection)
}
public func getSwarm(for publicKey: String, in transaction: YapDatabaseReadTransaction) -> [Snode] {
var result: [Snode] = []
let collection = getSwarmCollection(for: publicKey)
let collection = Storage.getSwarmCollection(for: publicKey)
transaction.enumerateKeysAndObjects(inCollection: collection) { _, object, _ in
guard let snode = object as? Snode else { return }
result.append(snode)
@ -64,15 +58,13 @@ public extension OWSPrimaryStorage {
// MARK: - Onion Request Paths
private static let onionRequestPathCollection = "LokiOnionRequestPathCollection"
public func setOnionRequestPaths(_ paths: [OnionRequestAPI.Path], in transaction: YapDatabaseReadWriteTransaction) {
// FIXME: This is a bit of a dirty approach that assumes 2 paths of length 3 each. We should do better than this.
guard paths.count == 2 else { return }
let path0 = paths[0]
let path1 = paths[1]
guard path0.count == 3, path1.count == 3 else { return }
let collection = OWSPrimaryStorage.onionRequestPathCollection
let collection = Storage.onionRequestPathCollection
transaction.setObject(path0[0], forKey: "0-0", inCollection: collection)
transaction.setObject(path0[1], forKey: "0-1", inCollection: collection)
transaction.setObject(path0[2], forKey: "0-2", inCollection: collection)
@ -82,7 +74,7 @@ public extension OWSPrimaryStorage {
}
public func getOnionRequestPaths(in transaction: YapDatabaseReadTransaction) -> [OnionRequestAPI.Path] {
let collection = OWSPrimaryStorage.onionRequestPathCollection
let collection = Storage.onionRequestPathCollection
guard
let path0Snode0 = transaction.object(forKey: "0-0", inCollection: collection) as? LokiAPITarget,
let path0Snode1 = transaction.object(forKey: "0-1", inCollection: collection) as? LokiAPITarget,
@ -94,20 +86,18 @@ public extension OWSPrimaryStorage {
}
public func clearOnionRequestPaths(in transaction: YapDatabaseReadWriteTransaction) {
transaction.removeAllObjects(inCollection: OWSPrimaryStorage.onionRequestPathCollection)
transaction.removeAllObjects(inCollection: Storage.onionRequestPathCollection)
}
// MARK: - Session Requests
private static let sessionRequestTimestampCollection = "LokiSessionRequestTimestampCollection"
public func setSessionRequestTimestamp(for publicKey: String, to timestamp: Date, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setDate(timestamp, forKey: publicKey, inCollection: OWSPrimaryStorage.sessionRequestTimestampCollection)
transaction.setDate(timestamp, forKey: publicKey, inCollection: Storage.sessionRequestTimestampCollection)
}
public func getSessionRequestTimestamp(for publicKey: String, in transaction: YapDatabaseReadTransaction) -> Date? {
transaction.date(forKey: publicKey, inCollection: OWSPrimaryStorage.sessionRequestTimestampCollection)
transaction.date(forKey: publicKey, inCollection: Storage.sessionRequestTimestampCollection)
}
@ -115,23 +105,15 @@ public extension OWSPrimaryStorage {
// MARK: - Multi Device
private static var deviceLinkCache: Set<DeviceLink> = []
private func getDeviceLinkCollection(for masterHexEncodedPublicKey: String) -> String {
return "LokiDeviceLinkCollection-\(masterHexEncodedPublicKey)"
}
public func cacheDeviceLinks(_ deviceLinks: Set<DeviceLink>) {
OWSPrimaryStorage.deviceLinkCache.formUnion(deviceLinks)
public func setDeviceLinks(_ deviceLinks: Set<DeviceLink>) {
deviceLinks.forEach { addDeviceLink($0) }
}
public func setDeviceLinks(_ deviceLinks: Set<DeviceLink>, in transaction: YapDatabaseReadWriteTransaction) {
deviceLinks.forEach { addDeviceLink($0, in: transaction) }
}
public func addDeviceLink(_ deviceLink: DeviceLink, in transaction: YapDatabaseReadWriteTransaction) {
public func addDeviceLink(_ deviceLink: DeviceLink) {
OWSPrimaryStorage.deviceLinkCache.insert(deviceLink)
}
public func removeDeviceLink(_ deviceLink: DeviceLink, in transaction: YapDatabaseReadWriteTransaction) {
public func removeDeviceLink(_ deviceLink: DeviceLink) {
OWSPrimaryStorage.deviceLinkCache.remove(deviceLink)
}
@ -150,13 +132,19 @@ public extension OWSPrimaryStorage {
// MARK: - Open Groups
private static let openGroupUserCountCollection = "LokiPublicChatUserCountCollection"
public func getUserCount(for publicChat: LokiPublicChat, in transaction: YapDatabaseReadTransaction) -> Int? {
return transaction.object(forKey: publicChat.id, inCollection: OWSPrimaryStorage.openGroupUserCountCollection) as? Int
return transaction.object(forKey: publicChat.id, inCollection: Storage.openGroupUserCountCollection) as? Int
}
public func setUserCount(_ userCount: Int, forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(userCount, forKey: publicChatID, inCollection: OWSPrimaryStorage.openGroupUserCountCollection)
transaction.setObject(userCount, forKey: publicChatID, inCollection: Storage.openGroupUserCountCollection)
}
public func getProfilePictureURL(forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadTransaction) -> String? {
return transaction.object(forKey: publicChatID, inCollection: Storage.openGroupProfilePictureURLCollection) as? String
}
public func setProfilePictureURL(_ profilePictureURL: String?, forPublicChatWithID publicChatID: String, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(profilePictureURL, forKey: publicChatID, inCollection: Storage.openGroupProfilePictureURLCollection)
}
}

View file

@ -13,6 +13,7 @@
@objc public static let onionRequestPathCollection = "LokiOnionRequestPathCollection"
@objc public static let openGroupCollection = "LokiPublicChatCollection"
@objc public static let openGroupProfilePictureURLCollection = "LokiPublicChatAvatarURLCollection"
@objc public static let openGroupUserCountCollection = "LokiPublicChatUserCountCollection"
@objc public static let sessionRequestTimestampCollection = "LokiSessionRequestTimestampCollection"
@objc public static let snodePoolCollection = "LokiSnodePoolCollection"

View file

@ -32,28 +32,40 @@ public final class Storage : NSObject {
// There can only be a single write transaction per database at any one time, so all write transactions must use `OWSPrimaryStorage`'s `dbReadWriteConnection`.
// Executing a write transaction from within a write transaction causes a deadlock and must be avoided.
@discardableResult
@objc(writeWithBlock:)
public static func objc_write(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void) -> AnyPromise {
return AnyPromise.from(write(with: block))
return AnyPromise.from(write(with: block) { })
}
@discardableResult
public static func write(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void) -> Promise<Void> {
return write(with: block) { }
}
@discardableResult
@objc(writeWithBlock:completion:)
public static func objc_write(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void, completion: @escaping () -> Void) -> AnyPromise {
return AnyPromise.from(write(with: block, completion: completion))
}
@discardableResult
public static func write(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void, completion: @escaping () -> Void) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending()
serialQueue.async { // TODO: There are cases where this isn't necessary
owsStorage.dbReadWriteConnection.readWrite(block)
serialQueue.async {
owsStorage.dbReadWriteConnection.readWrite { transaction in
transaction.addCompletionQueue(DispatchQueue.main, completionBlock: completion)
block(transaction)
}
seal.fulfill(())
}
return promise
}
/// Blocks the calling thread until the write has finished.
@objc(syncWriteWithBlock:error:)
public static func objc_syncWrite(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void) throws {
try syncWrite(with: block)
}
/// Blocks the calling thread until the write has finished.
public static func syncWrite(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void) throws {
try write(with: block).wait()
@discardableResult
@objc(writeSyncWithBlock:error:)
public static func writeSync(with block: @escaping (YapDatabaseReadWriteTransaction) -> Void) throws {
try write(with: block, completion: { }).wait()
}
}

View file

@ -38,6 +38,7 @@ public final class ClosedGroupsProtocol : NSObject {
guard hexEncodedPublicKey != getUserHexEncodedPublicKey() else { return }
let hasSession = storage.containsSession(hexEncodedPublicKey, deviceId: Int32(OWSDevicePrimaryDeviceId), protocolContext: transaction)
guard !hasSession else { return }
print("[Loki] Establishing session with: \(hexEncodedPublicKey).")
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
thread.save(with: transaction)
let sessionRequestMessage = SessionRequestMessage(thread: thread)

View file

@ -66,7 +66,7 @@ public final class FriendRequestExpirationJob : NSObject {
expireMessages()
var nextExpirationTimestamp: UInt64? = nil
databaseConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
nextExpirationTimestamp = self.messageFinder.nextExpirationTimestamp(with: transaction)
}
@ -108,7 +108,7 @@ public final class FriendRequestExpirationJob : NSObject {
guard let strongSelf = self else { return }
strongSelf.databaseConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
strongSelf.messageFinder.enumurateMessagesPendingExpiration(with: { message in
guard message.thread is TSContactThread else { return }

View file

@ -9,6 +9,9 @@ import PromiseKit
// Document the expected cases for everything.
// Express those cases in tests.
// FIXME: We're manually attaching the sender certificate and UD recipient access to message sends in a lot of places. It'd be great
// to clean this up and just do it in one spot.
@objc(LKMultiDeviceProtocol)
public final class MultiDeviceProtocol : NSObject {
@ -46,9 +49,15 @@ public final class MultiDeviceProtocol : NSObject {
storage.dbReadConnection.read { transaction in
recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction)
}
// TODO: Why is it okay that the thread, sender certificate, etc. don't get changed?
let udManager = SSKEnvironment.shared.udManager
let senderCertificate = udManager.getSenderCertificate()
var recipientUDAccess: OWSUDAccess?
if let senderCertificate = senderCertificate {
recipientUDAccess = udManager.udAccess(forRecipientId: destination.hexEncodedPublicKey, requireSyncAccess: true) // Starts a new write transaction internally
}
// TODO: Why is it okay that the thread doesn't get changed?
return OWSMessageSend(message: messageSend.message, thread: messageSend.thread, recipient: recipient,
senderCertificate: messageSend.senderCertificate, udAccess: messageSend.udAccess, localNumber: messageSend.localNumber, success: {
senderCertificate: senderCertificate, udAccess: recipientUDAccess, localNumber: messageSend.localNumber, success: {
seal.fulfill(())
}, failure: { error in
seal.reject(error)
@ -62,15 +71,12 @@ public final class MultiDeviceProtocol : NSObject {
} else if let thread = TSContactThread.getWithContactId(destination.hexEncodedPublicKey, transaction: transaction) {
threadPromiseSeal.fulfill(thread)
} else {
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
let thread = TSContactThread.getOrCreateThread(withContactId: destination.hexEncodedPublicKey, transaction: transaction)
threadPromiseSeal.fulfill(thread)
}
Storage.write { transaction in
let thread = TSContactThread.getOrCreateThread(withContactId: destination.hexEncodedPublicKey, transaction: transaction)
threadPromiseSeal.fulfill(thread)
}
}
return threadPromise.then(on: OWSDispatch.sendingQueue()) { thread -> Promise<Void> in
return threadPromise.then(on: DispatchQueue.main) { thread -> Promise<Void> in // Intentionally the main queue
let message = messageSend.message
let messageSender = SSKEnvironment.shared.messageSender
let (promise, seal) = Promise<Void>.pending()
@ -79,15 +85,14 @@ public final class MultiDeviceProtocol : NSObject {
&& message.shouldBeSaved() // shouldBeSaved indicates it isn't a transient message
if !shouldSendAutoGeneratedFR {
let messageSendCopy = copy(messageSend, for: destination, with: seal)
messageSender.sendMessage(messageSendCopy)
OWSDispatch.sendingQueue().async {
messageSender.sendMessage(messageSendCopy)
}
} else {
// Dispatch async on the main queue to avoid nested write transactions
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
getAutoGeneratedMultiDeviceFRMessageSend(for: destination.hexEncodedPublicKey, in: transaction, seal: seal)
.done(on: OWSDispatch.sendingQueue()) { autoGeneratedFRMessageSend in
messageSender.sendMessage(autoGeneratedFRMessageSend)
}
Storage.write { transaction in
getAutoGeneratedMultiDeviceFRMessageSend(for: destination.hexEncodedPublicKey, in: transaction, seal: seal)
.done(on: OWSDispatch.sendingQueue()) { autoGeneratedFRMessageSend in
messageSender.sendMessage(autoGeneratedFRMessageSend)
}
}
}
@ -137,10 +142,20 @@ public final class MultiDeviceProtocol : NSObject {
messageSend.failure(errors.first!)
}
}
}.catch(on: OWSDispatch.sendingQueue()) { error in
}.catch(on: DispatchQueue.main) { error in // Intentionally the main queue
// Proceed even if updating the recipient's device links failed, so that message sending
// is independent of whether the file server is online
messageSender.sendMessage(messageSend)
let udManager = SSKEnvironment.shared.udManager
let senderCertificate = udManager.getSenderCertificate()
var recipientUDAccess: OWSUDAccess?
if let senderCertificate = senderCertificate {
recipientUDAccess = udManager.udAccess(forRecipientId: recipientID, requireSyncAccess: true) // Starts a new write transaction internally
}
messageSend.senderCertificate = senderCertificate
messageSend.udAccess = recipientUDAccess
OWSDispatch.sendingQueue().async {
messageSender.sendMessage(messageSend)
}
}
}

View file

@ -146,14 +146,13 @@ public final class SessionManagementProtocol : NSObject {
hasSentSessionRequest = storage.getSessionRequestTimestamp(for: hexEncodedPublicKey, in: transaction) != nil
}
guard !hasSentSessionRequest else { return }
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
let sessionRequestMessage = SessionRequestMessage(thread: thread)
storage.setSessionRequestTimestamp(for: hexEncodedPublicKey, to: Date(), in: transaction)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: sessionRequestMessage, transaction: transaction)
}
Storage.write { transaction in
print("[Loki] Repairing session with: \(hexEncodedPublicKey).")
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
let sessionRequestMessage = SessionRequestMessage(thread: thread)
storage.setSessionRequestTimestamp(for: hexEncodedPublicKey, to: Date(), in: transaction)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: sessionRequestMessage, transaction: transaction)
}
}
@ -201,6 +200,7 @@ public final class SessionManagementProtocol : NSObject {
if let sentSessionRequestTimestamp = storage.getSessionRequestTimestamp(for: hexEncodedPublicKey, in: transaction),
envelope.timestamp < NSDate.ows_millisecondsSince1970(for: sentSessionRequestTimestamp) {
// We sent a session request after this one was sent
print("[Loki] Ignoring session request from: \(hexEncodedPublicKey).")
return
}
var closedGroupMembers: Set<String> = []
@ -210,7 +210,7 @@ public final class SessionManagementProtocol : NSObject {
closedGroupMembers.formUnion(group.groupModel.groupMemberIds)
}
LokiFileServerAPI.getDeviceLinks(associatedWith: closedGroupMembers).ensure {
storage.dbReadWriteConnection.readWrite { transaction in
Storage.write { transaction in
let validHEPKs = closedGroupMembers.flatMap {
LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: $0, in: transaction)
}

View file

@ -23,6 +23,22 @@ public final class SyncMessagesProtocol : NSObject {
// FIXME: We added this check to avoid a crash, but we should really figure out why that crash was happening in the first place
return !UserDefaults.standard[.hasLaunchedOnce]
}
@objc(syncProfile)
public static func syncProfile() {
try! Storage.writeSync { transaction in
let userPublicKey = getUserHexEncodedPublicKey()
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: userPublicKey, in: transaction)
for publicKey in linkedDevices {
guard publicKey != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: publicKey, transaction: transaction)
let syncMessage = OWSOutgoingSyncMessage.init(in: thread, messageBody: "", attachmentId: nil)
syncMessage.save(with: transaction)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: syncMessage, transaction: transaction)
}
}
}
@objc(syncContactWithHexEncodedPublicKey:in:)
public static func syncContact(_ hexEncodedPublicKey: String, in transaction: YapDatabaseReadTransaction) -> AnyPromise {
@ -97,6 +113,12 @@ public final class SyncMessagesProtocol : NSObject {
return LokiDatabaseUtilities.isUserLinkedDevice(hexEncodedPublicKey, transaction: transaction)
}
public static func dropFromSyncMessageTimestampCache(_ timestamp: UInt64, for hexEncodedPublicKey: String) {
var timestamps: Set<UInt64> = syncMessageTimestamps[hexEncodedPublicKey] ?? []
if timestamps.contains(timestamp) { timestamps.remove(timestamp) }
syncMessageTimestamps[hexEncodedPublicKey] = timestamps
}
// TODO: We should probably look at why sync messages are being duplicated rather than doing this
@objc(isDuplicateSyncMessage:fromHexEncodedPublicKey:)
public static func isDuplicateSyncMessage(_ protoContent: SSKProtoContent, from hexEncodedPublicKey: String) -> Bool {
@ -166,9 +188,10 @@ public final class SyncMessagesProtocol : NSObject {
let parser = ContactParser(data: data)
let hexEncodedPublicKeys = parser.parseHexEncodedPublicKeys()
let userHexEncodedPublicKey = getUserHexEncodedPublicKey()
let linkedDevices = LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: userHexEncodedPublicKey, in: transaction)
// Try to establish sessions
for hexEncodedPublicKey in hexEncodedPublicKeys {
guard hexEncodedPublicKey != userHexEncodedPublicKey else { continue } // Skip self
guard !linkedDevices.contains(hexEncodedPublicKey) else { continue } // Skip self and linked devices
// We don't update the friend request status; that's done in OWSMessageSender.sendMessage(_:)
let friendRequestStatus = storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction)
switch friendRequestStatus {
@ -228,6 +251,9 @@ public final class SyncMessagesProtocol : NSObject {
for openGroup in groups {
let openGroupManager = LokiPublicChatManager.shared
guard openGroupManager.getChat(server: openGroup.url, channel: openGroup.channel) == nil else { return }
let userPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] ?? getUserHexEncodedPublicKey()
let displayName = SSKEnvironment.shared.profileManager.profileNameForRecipient(withID: userPublicKey)
LokiPublicChatAPI.setDisplayName(to: displayName, on: openGroup.url)
openGroupManager.addChat(server: openGroup.url, channel: openGroup.channel)
}
}

View file

@ -287,27 +287,26 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
self.downloadingJobMap[job.attachmentPointer.uniqueId] = job;
}
[self.primaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
job.attachmentPointer.state = TSAttachmentPointerStateDownloading;
[job.attachmentPointer saveWithTransaction:transaction];
if (job.message) {
[job.message touchWithTransaction:transaction];
}
}];
} error:nil];
[self retrieveAttachmentForJob:job
success:^(TSAttachmentStream *attachmentStream) {
OWSLogVerbose(@"Attachment download succeeded.");
[self.primaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[attachmentStream saveWithTransaction:transaction];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[attachmentStream saveWithTransaction:transaction];
if (job.message) {
[job.message touchWithTransaction:transaction];
}
}];
if (job.message) {
[job.message touchWithTransaction:transaction];
}
} error:nil];
job.success(attachmentStream);
@ -320,16 +319,15 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
failure:^(NSError *error) {
OWSLogError(@"Attachment download failed with error: %@", error);
[self.primaryStorage.dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
job.attachmentPointer.mostRecentFailureLocalizedText = error.localizedDescription;
job.attachmentPointer.state = TSAttachmentPointerStateFailed;
[job.attachmentPointer saveWithTransaction:transaction];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
job.attachmentPointer.mostRecentFailureLocalizedText = error.localizedDescription;
job.attachmentPointer.state = TSAttachmentPointerStateFailed;
[job.attachmentPointer saveWithTransaction:transaction];
if (job.message) {
[job.message touchWithTransaction:transaction];
}
}];
if (job.message) {
[job.message touchWithTransaction:transaction];
}
} error:nil];
@synchronized(self) {
[self.downloadingJobMap removeObjectForKey:job.attachmentPointer.uniqueId];

View file

@ -545,7 +545,7 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail);
{
OWSAssertDebug(changeBlock);
[self.dbReadWriteConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSString *collection = [TSAttachmentStream collection];
TSAttachmentStream *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
if (!latestInstance) {

View file

@ -389,7 +389,7 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
if (attachmentIds.count < 1) {
return;
}
[self.dbReadWriteConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *attachmentId in attachmentIds) {
// We need to fetch each attachment, since [TSAttachment removeWithTransaction:] does important work.
TSAttachment *_Nullable attachment =
@ -672,9 +672,9 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
- (void)updateWithCustomMessage:(NSString *)customMessage
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithCustomMessage:customMessage transaction:transaction];
}];
} error:nil];
}
- (void)saveIsCalculatingProofOfWork:(BOOL)isCalculatingPoW withTransaction:(YapDatabaseReadWriteTransaction *)transaction
@ -1125,24 +1125,27 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
}
- (SSKProtoContentBuilder *)prepareCustomContentBuilder:(SignalRecipient *)recipient {
return SSKProtoContent.builder;
SSKProtoDataMessage *_Nullable dataMessage = [self buildDataMessage:recipient.recipientId];
if (!dataMessage) {
OWSFailDebug(@"Couldn't build protobuf.");
return nil;
}
SSKProtoContentBuilder *contentBuilder = SSKProtoContent.builder;
[contentBuilder setDataMessage:dataMessage];
return contentBuilder;
}
- (nullable NSData *)buildPlainTextData:(SignalRecipient *)recipient
{
NSError *error;
SSKProtoDataMessage *_Nullable dataMessage = [self buildDataMessage:recipient.recipientId];
if (error || !dataMessage) {
OWSFailDebug(@"could not build protobuf: %@", error);
return nil;
}
SSKProtoContentBuilder *contentBuilder = [self prepareCustomContentBuilder:recipient];
[contentBuilder setDataMessage:dataMessage];
NSError *error;
NSData *_Nullable contentData = [contentBuilder buildSerializedDataAndReturnError:&error];
if (error || !contentData) {
OWSFailDebug(@"could not serialize protobuf: %@", error);
OWSFailDebug(@"Couldn't serialize protobuf due to error: %@.", error);
return nil;
}

View file

@ -168,9 +168,9 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo
- (void)removeJobsWithIds:(NSArray<NSString *> *)uniqueIds
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectsForKeys:uniqueIds inCollection:[OWSMessageContentJob collection]];
}];
} error:nil];
}
+ (YapDatabaseView *)databaseExtension
@ -418,7 +418,7 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo
AssertOnDispatchQueue(self.serialQueue);
NSMutableArray<OWSMessageContentJob *> *processedJobs = [NSMutableArray new];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSMessageContentJob *job in jobs) {
void (^reportFailure)(YapDatabaseReadWriteTransaction *transaction) = ^(
@ -453,7 +453,7 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo
break;
}
}
}];
} error:nil];
return processedJobs;
}

View file

@ -17,6 +17,7 @@
#import "TSMessage.h"
#import "TSThread.h"
#import <SessionCoreKit/NSDate+OWS.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -126,7 +127,7 @@ void AssertIsOnDisappearingMessagesQueue()
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
__block NSUInteger expirationCount = 0;
[self.databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.disappearingMessagesFinder enumerateExpiredMessagesWithBlock:^(TSMessage *message) {
// sanity check
if (message.expiresAt > now) {
@ -139,7 +140,7 @@ void AssertIsOnDisappearingMessagesQueue()
expirationCount++;
}
transaction:transaction];
}];
} error:nil];
OWSLogDebug(@"Removed %lu expired messages", (unsigned long)expirationCount);
@ -266,9 +267,9 @@ void AssertIsOnDisappearingMessagesQueue()
dispatch_async(OWSDisappearingMessagesJob.serialQueue, ^{
// Theoretically this shouldn't be necessary, but there was a race condition when receiving a backlog
// of messages across timer changes which could cause a disappearing message's timer to never be started.
[self.databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self cleanupMessagesWhichFailedToStartExpiringWithTransaction:transaction];
}];
} error:nil];
[self runLoop];
});

View file

@ -8,6 +8,7 @@
#import <YapDatabase/YapDatabase.h>
#import <YapDatabase/YapDatabaseQuery.h>
#import <YapDatabase/YapDatabaseSecondaryIndex.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -77,18 +78,17 @@ static NSString *const OWSFailedAttachmentDownloadsJobAttachmentStateIndex = @"i
- (void)run
{
__block uint count = 0;
[[self.primaryStorage newDatabaseConnection]
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self enumerateAttemptingOutAttachmentsWithBlock:^(TSAttachmentPointer *attachment) {
// sanity check
if (attachment.state != TSAttachmentPointerStateFailed) {
attachment.state = TSAttachmentPointerStateFailed;
[attachment saveWithTransaction:transaction];
count++;
}
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self enumerateAttemptingOutAttachmentsWithBlock:^(TSAttachmentPointer *attachment) {
// sanity check
if (attachment.state != TSAttachmentPointerStateFailed) {
attachment.state = TSAttachmentPointerStateFailed;
[attachment saveWithTransaction:transaction];
count++;
}
transaction:transaction];
}];
}
transaction:transaction];
} error:nil];
OWSLogDebug(@"Marked %u attachments as unsent", count);
}

View file

@ -9,6 +9,7 @@
#import <YapDatabase/YapDatabase.h>
#import <YapDatabase/YapDatabaseQuery.h>
#import <YapDatabase/YapDatabaseSecondaryIndex.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -79,24 +80,23 @@ static NSString *const OWSFailedMessagesJobMessageStateIndex = @"index_outoing_m
{
__block uint count = 0;
[[self.primaryStorage newDatabaseConnection]
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self enumerateAttemptingOutMessagesWithBlock:^(TSOutgoingMessage *message) {
// sanity check
OWSAssertDebug(message.messageState == TSOutgoingMessageStateSending);
if (message.messageState != TSOutgoingMessageStateSending) {
OWSLogError(@"Refusing to mark as unsent message with state: %d", (int)message.messageState);
return;
}
OWSLogDebug(@"marking message as unsent: %@", message.uniqueId);
[message updateWithAllSendingRecipientsMarkedAsFailedWithTansaction:transaction];
OWSAssertDebug(message.messageState == TSOutgoingMessageStateFailed);
count++;
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self enumerateAttemptingOutMessagesWithBlock:^(TSOutgoingMessage *message) {
// sanity check
OWSAssertDebug(message.messageState == TSOutgoingMessageStateSending);
if (message.messageState != TSOutgoingMessageStateSending) {
OWSLogError(@"Refusing to mark as unsent message with state: %d", (int)message.messageState);
return;
}
transaction:transaction];
}];
OWSLogDebug(@"marking message as unsent: %@", message.uniqueId);
[message updateWithAllSendingRecipientsMarkedAsFailedWithTansaction:transaction];
OWSAssertDebug(message.messageState == TSOutgoingMessageStateFailed);
count++;
}
transaction:transaction];
} error:nil];
OWSLogDebug(@"Marked %u messages as unsent", count);
}

View file

@ -206,9 +206,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
OWSAssertDebug(recipientId.length > 0);
__block BOOL result;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
result = [self saveRemoteIdentity:identityKey recipientId:recipientId protocolContext:transaction];
}];
} error:nil];
return result;
}
@ -294,13 +294,13 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
OWSAssertDebug(identityKey.length == kStoredIdentityKeyLength);
OWSAssertDebug(recipientId.length > 0);
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self setVerificationState:verificationState
identityKey:identityKey
recipientId:recipientId
isUserInitiatedChange:isUserInitiatedChange
transaction:transaction];
}];
} error:nil];
}
- (void)setVerificationState:(OWSVerificationState)verificationState
@ -663,10 +663,10 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
OWSLogInfo(@"Successfully sent verification state sync message");
// Record that this verification state was successfully synced.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self clearSyncMessageForRecipientId:message.verificationForRecipientId
transaction:transaction];
}];
} error:nil];
}
failure:^(NSError *error) {
OWSLogError(@"Failed to send verification state sync message with error: %@", error);
@ -678,9 +678,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
OWSLogInfo(@"Removing retries for syncing verification state, since user is no longer registered: %@",
message.verificationForRecipientId);
// Otherwise this will fail forever.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self clearSyncMessageForRecipientId:message.verificationForRecipientId transaction:transaction];
}];
} error:nil];
}
}];
}

View file

@ -10,6 +10,7 @@
#import <YapDatabase/YapDatabase.h>
#import <YapDatabase/YapDatabaseQuery.h>
#import <YapDatabase/YapDatabaseSecondaryIndex.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -83,7 +84,7 @@ static NSString *const OWSIncompleteCallsJobCallTypeIndex = @"index_calls_on_cal
OWSAssertDebug(CurrentAppContext().appLaunchTime);
uint64_t cutoffTimestamp = [NSDate ows_millisecondsSince1970ForDate:CurrentAppContext().appLaunchTime];
[[self.primaryStorage newDatabaseConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self
enumerateIncompleteCallsWithBlock:^(TSCall *call) {
if (call.timestamp <= cutoffTimestamp) {
@ -106,7 +107,7 @@ static NSString *const OWSIncompleteCallsJobCallTypeIndex = @"index_calls_on_cal
count++;
}
transaction:transaction];
}];
} error:nil];
OWSLogInfo(@"Marked %u calls as missed", count);
}

View file

@ -216,7 +216,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
switch (envelope.type) {
case SSKProtoEnvelopeTypeFriendRequest: {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self decryptFriendRequestMessage:envelope
envelopeData:envelopeData
successBlock:^(OWSMessageDecryptResult *result) {
@ -229,7 +229,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
error);
failureBlock();
}];
}];
} error:nil];
// Return to avoid double-acknowledging
return;
}
@ -271,7 +271,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
case SSKProtoEnvelopeTypeReceipt:
case SSKProtoEnvelopeTypeKeyExchange:
case SSKProtoEnvelopeTypeUnknown: {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
OWSMessageDecryptResult *result =
[OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
plaintextData:nil
@ -279,7 +279,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
sourceDevice:envelope.sourceDevice
isUDMessage:NO];
successBlock(result, transaction);
}];
} error:nil];
// Return to avoid double-acknowledging.
return;
}
@ -307,12 +307,11 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
OWSFailDebug(@"Received an invalid envelope: %@.", exception.debugDescription);
OWSProdFail([OWSAnalyticsEvents messageManagerErrorInvalidProtocolMessage]);
[[self.primaryStorage newDatabaseConnection]
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage corruptedMessageInUnknownThread];
[SSKEnvironment.shared.notificationsManager notifyUserForThreadlessErrorMessage:errorMessage
transaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage corruptedMessageInUnknownThread];
[SSKEnvironment.shared.notificationsManager notifyUserForThreadlessErrorMessage:errorMessage
transaction:transaction];
} error:nil];
}
failureBlock();
@ -422,43 +421,42 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
return failureBlock(error);
}
[self.dbConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
id<CipherMessage> cipherMessage = cipherMessageBlock(encryptedData);
LKSessionCipher *cipher = [[LKSessionCipher alloc]
initWithSessionResetImplementation:self.sessionResetImplementation
sessionStore:self.primaryStorage
preKeyStore:self.primaryStorage
signedPreKeyStore:self.primaryStorage
identityKeyStore:self.identityManager
recipientID:recipientId
deviceID:deviceId];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
id<CipherMessage> cipherMessage = cipherMessageBlock(encryptedData);
LKSessionCipher *cipher = [[LKSessionCipher alloc]
initWithSessionResetImplementation:self.sessionResetImplementation
sessionStore:self.primaryStorage
preKeyStore:self.primaryStorage
signedPreKeyStore:self.primaryStorage
identityKeyStore:self.identityManager
recipientID:recipientId
deviceID:deviceId];
// plaintextData may be nil for some envelope types.
NSError *error = nil;
NSData *_Nullable decryptedData = [cipher decrypt:cipherMessage protocolContext:transaction error:&error];
// Throw if we got an error
SCKRaiseIfExceptionWrapperError(error);
NSData *_Nullable plaintextData = decryptedData != nil ? [decryptedData removePadding] : nil;
OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
plaintextData:plaintextData
source:envelope.source
sourceDevice:envelope.sourceDevice
isUDMessage:NO];
successBlock(result, transaction);
} @catch (NSException *exception) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self processException:exception envelope:envelope];
NSString *errorDescription = [NSString
stringWithFormat:@"Exception while decrypting %@: %@.", cipherTypeName, exception.description];
OWSLogError(@"%@", errorDescription);
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription);
failureBlock(error);
});
}
}];
// plaintextData may be nil for some envelope types.
NSError *error = nil;
NSData *_Nullable decryptedData = [cipher decrypt:cipherMessage protocolContext:transaction error:&error];
// Throw if we got an error
SCKRaiseIfExceptionWrapperError(error);
NSData *_Nullable plaintextData = decryptedData != nil ? [decryptedData removePadding] : nil;
OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
plaintextData:plaintextData
source:envelope.source
sourceDevice:envelope.sourceDevice
isUDMessage:NO];
successBlock(result, transaction);
} @catch (NSException *exception) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self processException:exception envelope:envelope];
NSString *errorDescription = [NSString
stringWithFormat:@"Exception while decrypting %@: %@.", cipherTypeName, exception.description];
OWSLogError(@"%@", errorDescription);
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription);
failureBlock(error);
});
}
}];
}
- (void)decryptUnidentifiedSender:(SSKProtoEnvelope *)envelope
@ -486,7 +484,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
NSString *localRecipientId = self.tsAccountManager.localNumber;
uint32_t localDeviceId = OWSDevicePrimaryDeviceId;
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSError *cipherError;
SMKSecretSessionCipher *_Nullable cipher =
[[SMKSecretSessionCipher alloc] initWithSessionResetImplementation:self.sessionResetImplementation
@ -580,7 +578,6 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
return;
}
OWSFailDebug(@"Could not decrypt UD message: %@.", underlyingError);
failureBlock(underlyingError);
return;
}
@ -635,7 +632,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
OWSLogError(
@"Got exception: %@ of type: %@ with reason: %@", exception.description, exception.name, exception.reason);
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage;
if (envelope.source.length == 0) {
@ -676,7 +673,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
[LKSessionManagementProtocol handleDecryptionError:errorMessage.errorType forHexEncodedPublicKey:envelope.source using:transaction];
[self notifyUserForErrorMessage:errorMessage envelope:envelope transaction:transaction];
}
}];
} error:nil];
}
- (void)notifyUserForErrorMessage:(TSErrorMessage *)errorMessage

View file

@ -938,7 +938,7 @@ NS_ASSUME_NONNULL_BEGIN
attachmentHandler:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
OWSAssertDebug(attachmentStreams.count == 1);
TSAttachmentStream *attachmentStream = attachmentStreams.firstObject;
[self.dbConnection readWriteWithBlock:^(
[LKStorage writeSyncWithBlock:^(
YapDatabaseReadWriteTransaction *transaction) {
TSGroupThread *_Nullable groupThread =
[TSGroupThread threadWithGroupId:dataMessage.group.id
@ -950,7 +950,7 @@ NS_ASSUME_NONNULL_BEGIN
[groupThread updateAvatarWithAttachmentStream:attachmentStream
transaction:transaction];
}];
} error:nil];
}
transaction:transaction
];
@ -1636,7 +1636,7 @@ NS_ASSUME_NONNULL_BEGIN
// * Failures don't interfere with successes.
[self.attachmentDownloads downloadAttachmentPointer:attachmentPointer
success:^(NSArray<TSAttachmentStream *> *attachmentStreams) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSAttachmentStream *_Nullable attachmentStream = attachmentStreams.firstObject;
OWSAssertDebug(attachmentStream);
if (attachmentStream && incomingMessage.quotedMessage.thumbnailAttachmentPointerId.length > 0 &&
@ -1649,7 +1649,7 @@ NS_ASSUME_NONNULL_BEGIN
// since the attachment might be a contact avatar, etc.
[incomingMessage touchWithTransaction:transaction];
}
}];
} error:nil];
}
failure:^(NSError *error) {
OWSLogWarn(@"Failed to download attachment for message: %lu with error: %@.",

View file

@ -136,17 +136,17 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
- (void)addJobForEnvelopeData:(NSData *)envelopeData
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
OWSMessageDecryptJob *job = [[OWSMessageDecryptJob alloc] initWithEnvelopeData:envelopeData];
[job saveWithTransaction:transaction];
}];
} error:nil];
}
- (void)removeJobWithId:(NSString *)uniqueId
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectForKey:uniqueId inCollection:[OWSMessageDecryptJob collection]];
}];
} error:nil];
}
+ (YapDatabaseView *)databaseExtension
@ -375,11 +375,11 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
if (!envelope) {
OWSFailDebug(@"Couldn't parse proto.");
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage corruptedMessageInUnknownThread];
[SSKEnvironment.shared.notificationsManager notifyUserForThreadlessErrorMessage:errorMessage
transaction:transaction];
}];
} error:nil];
dispatch_async(self.serialQueue, ^{
completion(NO);

View file

@ -366,11 +366,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
if ([LKFriendRequestProtocol shouldUpdateFriendRequestStatusFromMessage:message]) {
[self.primaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Loki: Optimistically update friend request status when we can. This is used for
// e.g. preventing AFRs from being sent twice on a contact sync.
[LKFriendRequestProtocol setFriendRequestStatusToSendingIfNeededForHexEncodedPublicKey:message.thread.contactIdentifier transaction:transaction];
}];
} error:nil];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -388,10 +388,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
//
// So we're using YDB behavior to ensure this invariant, which is a bit
// unorthodox.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[allAttachmentIds
addObjectsFromArray:[OutgoingMessagePreparer prepareMessageForSending:message transaction:transaction]];
}];
} error:nil];
NSOperationQueue *sendingQueue = [self sendingQueueForMessage:message];
OWSSendMessageOperation *sendMessageOperation =
@ -610,11 +610,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}];
if ([LKMultiDeviceProtocol isMultiDeviceRequiredForMessage:message]) { // Avoid the write transaction if possible
dispatch_async(dispatch_get_main_queue(), ^{
[self.primaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKMultiDeviceProtocol sendMessageToDestinationAndLinkedDevices:messageSend in:transaction];
}];
});
[self.primaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[LKMultiDeviceProtocol sendMessageToDestinationAndLinkedDevices:messageSend in:transaction];
}];
} else {
[self sendMessage:messageSend];
}
@ -717,12 +715,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
NSMutableSet<NSString *> *obsoleteRecipientIds = [NSMutableSet setWithArray:message.sendingRecipientIds];
[obsoleteRecipientIds minusSet:[NSSet setWithArray:recipientIds]];
if (obsoleteRecipientIds.count > 0) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *recipientId in obsoleteRecipientIds) {
// Mark this recipient as "skipped".
[message updateWithSkippedRecipient:recipientId transaction:transaction];
}
}];
} error:nil];
}
if (recipientIds.count < 1) {
@ -806,7 +804,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
message:(TSOutgoingMessage *)message
thread:(TSThread *)thread
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (thread.isGroupThread) {
// Mark as "skipped" group members who no longer have signal accounts.
[message updateWithSkippedRecipient:recipient.recipientId transaction:transaction];
@ -824,7 +822,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// TODO: Should we deleteAllSessionsForContact here?
// If so, we'll need to avoid doing a prekey fetch every
// time we try to send a message to an unregistered user.
}];
} error:nil];
}
- (nullable NSArray<NSDictionary *> *)deviceMessagesForMessageSend:(OWSMessageSend *)messageSend
@ -930,6 +928,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
{
OWSAssertDebug(messageSend);
OWSAssertDebug(messageSend.thread || [messageSend.message isKindOfClass:[OWSOutgoingSyncMessage class]]);
OWSAssertDebug(messageSend.isUDSend);
TSOutgoingMessage *message = messageSend.message;
SignalRecipient *recipient = messageSend.recipient;
@ -1053,9 +1052,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
dispatch_async([OWSDispatch sendingQueue], ^{
// This emulates the completion logic of an actual successful send (see below).
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message updateWithSkippedRecipient:messageSend.localNumber transaction:transaction];
}];
} error:nil];
messageSend.success();
});
@ -1170,10 +1169,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
message.actualSenderHexEncodedPublicKey = userHexEncodedPublicKey;
[[LKPublicChatAPI sendMessage:groupMessage toGroup:publicChat.channel onServer:publicChat.server]
.thenOn(OWSDispatch.sendingQueue, ^(LKGroupMessage *groupMessage) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message saveOpenGroupServerMessageID:groupMessage.serverID in:transaction];
[self.primaryStorage setIDForMessageWithServerID:groupMessage.serverID to:message.uniqueId in:transaction];
}];
} error:nil];
[self messageSendDidSucceed:messageSend deviceMessages:deviceMessages wasSentByUD:messageSend.isUDSend wasSentByWebsocket:false];
})
.catchOn(OWSDispatch.sendingQueue, ^(NSError *error) {
@ -1204,7 +1203,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
BOOL isPing = ((NSNumber *)signalMessageInfo[@"isPing"]).boolValue;
LKSignalMessage *signalMessage = [[LKSignalMessage alloc] initWithType:type timestamp:timestamp senderID:senderID senderDeviceID:senderDeviceID content:content recipientID:recipientID ttl:ttl isPing:isPing];
BOOL shouldUpdateFriendRequestStatus = [LKFriendRequestProtocol shouldUpdateFriendRequestStatusFromMessage:message];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (!message.skipSave) {
// Update the PoW calculation status
[message saveIsCalculatingProofOfWork:YES withTransaction:transaction];
@ -1212,11 +1211,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
if (shouldUpdateFriendRequestStatus) {
[LKFriendRequestProtocol setFriendRequestStatusToSendingIfNeededForHexEncodedPublicKey:recipientID transaction:transaction];
}
}];
} error:nil];
// Convenience
void (^onP2PSuccess)() = ^() { message.isP2P = YES; };
void (^handleError)(NSError *error) = ^(NSError *error) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (!message.skipSave) {
// Update the PoW calculation status
[message saveIsCalculatingProofOfWork:NO withTransaction:transaction];
@ -1224,7 +1223,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
if (shouldUpdateFriendRequestStatus) {
[LKFriendRequestProtocol setFriendRequestStatusToFailedIfNeededForHexEncodedPublicKey:recipientID transaction:transaction];
}
}];
} error:nil];
// Handle the error
failedMessageSend(error);
};
@ -1242,7 +1241,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.messageSent object:[[NSNumber alloc] initWithUnsignedLongLong:signalMessage.timestamp]];
isSuccess = YES;
if (shouldUpdateFriendRequestStatus) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (!message.skipSave) {
// Update the message
NSTimeInterval expirationInterval = 72 * kHourInterval;
@ -1250,7 +1249,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[message saveFriendRequestExpiresAt:[NSDate ows_millisecondsSince1970ForDate:expirationDate] withTransaction:transaction];
}
[LKFriendRequestProtocol setFriendRequestStatusToSentIfNeededForHexEncodedPublicKey:recipientID transaction:transaction];
}];
} error:nil];
}
// Invoke the completion handler
[self messageSendDidSucceed:messageSend deviceMessages:deviceMessages wasSentByUD:messageSend.isUDSend wasSentByWebsocket:false];
@ -1295,7 +1294,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
dispatch_async([OWSDispatch sendingQueue], ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[messageSend.message updateWithSentRecipient:messageSend.recipient.uniqueId
wasSentByUD:wasSentByUD
transaction:transaction];
@ -1303,7 +1302,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// If we've just delivered a message to a user, we know they
// have a valid Signal account.
[SignalRecipient markRecipientAsRegisteredAndGet:recipient.recipientId transaction:transaction];
}];
} error:nil];
messageSend.success();
});
@ -1465,29 +1464,28 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
}
[self.dbConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (extraDevices.count < 1 && missingDevices.count < 1) {
OWSProdFail([OWSAnalyticsEvents messageSenderErrorNoMissingOrExtraDevices]);
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (extraDevices.count < 1 && missingDevices.count < 1) {
OWSProdFail([OWSAnalyticsEvents messageSenderErrorNoMissingOrExtraDevices]);
}
[recipient updateRegisteredRecipientWithDevicesToAdd:missingDevices
devicesToRemove:extraDevices
transaction:transaction];
if (extraDevices && extraDevices.count > 0) {
OWSLogInfo(@"Deleting sessions for extra devices: %@", extraDevices);
for (NSNumber *extraDeviceId in extraDevices) {
[self.primaryStorage deleteSessionForContact:recipient.uniqueId
deviceId:extraDeviceId.intValue
protocolContext:transaction];
}
}
[recipient updateRegisteredRecipientWithDevicesToAdd:missingDevices
devicesToRemove:extraDevices
transaction:transaction];
if (extraDevices && extraDevices.count > 0) {
OWSLogInfo(@"Deleting sessions for extra devices: %@", extraDevices);
for (NSNumber *extraDeviceId in extraDevices) {
[self.primaryStorage deleteSessionForContact:recipient.uniqueId
deviceId:extraDeviceId.intValue
protocolContext:transaction];
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
completionHandler();
});
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
completionHandler();
});
} error:nil];
}
- (void)handleMessageSentLocally:(TSOutgoingMessage *)message
@ -1499,21 +1497,21 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// Loki: Take into account multi device
BOOL isNoteToSelf = [LKSessionMetaProtocol isThreadNoteToSelf:message.thread];
if (isNoteToSelf && !([message isKindOfClass:LKDeviceLinkMessage.class])) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *recipientId in message.sendingRecipientIds) {
[message updateWithReadRecipientId:recipientId readTimestamp:message.timestamp transaction:transaction];
}
}];
} error:nil];
}
successParam();
};
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:message
expirationStartedAt:[NSDate ows_millisecondTimeStamp]
transaction:transaction];
}];
} error:nil];
if (!message.shouldSyncTranscript) {
return success();
@ -1529,9 +1527,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
sendSyncTranscriptForMessage:message
isRecipientUpdate:isRecipientUpdate
success:^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message updateWithHasSyncedTranscript:YES transaction:transaction];
}];
} error:nil];
success();
}
@ -1563,9 +1561,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
NSString *recipientId = otherDevice ?: currentDevice;
__block SignalRecipient *recipient;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
recipient = [SignalRecipient markRecipientAsRegisteredAndGet:recipientId transaction:transaction];
}];
} error:nil];
SMKSenderCertificate *senderCertificate = [self.udManager getSenderCertificate];
OWSUDAccess *recipientUDAccess = nil;
@ -1636,17 +1634,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
__block NSDictionary *_Nullable messageDict;
__block NSException *encryptionException;
[self.dbConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
messageDict = [self throws_encryptedMessageForMessageSend:messageSend
recipientID:recipientID
plainText:plainText
transaction:transaction];
} @catch (NSException *exception) {
encryptionException = exception;
}
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
messageDict = [self throws_encryptedMessageForMessageSend:messageSend
recipientID:recipientID
plainText:plainText
transaction:transaction];
} @catch (NSException *exception) {
encryptionException = exception;
}
} error:nil];
if (encryptionException) {
OWSLogInfo(@"Exception during encryption: %@.", encryptionException);
@ -1660,11 +1657,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
} @catch (NSException *exception) {
if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient updateRegisteredRecipientWithDevicesToAdd:nil
devicesToRemove:@[ @(OWSDevicePrimaryDeviceId) ]
transaction:transaction];
}];
} error:nil];
} else {
@throw exception;
}
@ -1684,9 +1681,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSAssertDebug(recipientID.length > 0);
__block BOOL hasSession;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
hasSession = [storage containsSession:recipientID deviceId:[deviceId intValue] protocolContext:transaction];
}];
} error:nil];
if (hasSession) {
return YES;
}
@ -1747,7 +1744,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
identityKeyStore:self.identityManager
recipientId:recipientID
deviceId:[deviceId intValue]];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
[builder throws_processPrekeyBundle:bundle protocolContext:transaction];
@ -1756,7 +1753,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} @catch (NSException *caughtException) {
exception = caughtException;
}
}];
} error:nil];
if (exception) {
if ([exception.name isEqualToString:UntrustedIdentityKeyException]) {
OWSRaiseExceptionWithUserInfo(UntrustedIdentityKeyException,
@ -2009,7 +2006,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return;
}
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSUInteger i = 0; i < [devices count]; i++) {
int deviceNumber = [devices[i] intValue];
[[OWSPrimaryStorage sharedManager] deleteSessionForContact:identifier
@ -2115,7 +2112,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[attachmentStreams addObject:attachmentStream];
}
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
for (TSAttachmentStream *attachmentStream in attachmentStreams) {
[outgoingMessage.attachmentIds addObject:attachmentStream.uniqueId];
if (attachmentStream.sourceFilename) {
@ -2126,7 +2123,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
for (TSAttachmentStream *attachmentStream in attachmentStreams) {
[attachmentStream saveWithTransaction:transaction];
}
}];
} error:nil];
completionHandler(nil);
});

View file

@ -249,14 +249,14 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa
return;
}
dispatch_async(self.serialQueue, ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSSet<NSNumber *> *_Nullable oldTimestamps = [transaction objectForKey:recipientId inCollection:collection];
NSMutableSet<NSNumber *> *newTimestamps
= (oldTimestamps ? [oldTimestamps mutableCopy] : [NSMutableSet new]);
[newTimestamps addObject:@(timestamp)];
[transaction setObject:newTimestamps forKey:recipientId inCollection:collection];
}];
} error:nil];
[self process];
});
@ -276,7 +276,7 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa
return;
}
dispatch_async(self.serialQueue, ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSSet<NSNumber *> *_Nullable oldTimestamps = [transaction objectForKey:recipientId inCollection:collection];
NSMutableSet<NSNumber *> *newTimestamps
= (oldTimestamps ? [oldTimestamps mutableCopy] : [NSMutableSet new]);
@ -287,7 +287,7 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa
} else {
[transaction removeObjectForKey:recipientId inCollection:collection];
}
}];
} error:nil];
});
}

View file

@ -217,9 +217,9 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
OWSReadReceiptsForLinkedDevicesMessage *message =
[[OWSReadReceiptsForLinkedDevicesMessage alloc] initWithReadReceipts:readReceiptsForLinkedDevices];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:message transaction:transaction];
}];
} error:nil];
}
BOOL didWork = readReceiptsForLinkedDevices.count > 0;
@ -250,13 +250,13 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
OWSAssertDebug(thread);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self markAsReadBeforeSortId:sortId
thread:thread
readTimestamp:[NSDate ows_millisecondTimeStamp]
wasLocal:YES
transaction:transaction];
}];
} error:nil];
});
}
@ -315,7 +315,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSNumber *nsSentTimestamp in sentTimestamps) {
UInt64 sentTimestamp = [nsSentTimestamp unsignedLongLongValue];
@ -343,7 +343,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
transaction:transaction];
}
}
}];
} error:nil];
});
}

View file

@ -6,6 +6,7 @@
#import "TSContactThread.h"
#import <YapDatabase/YapDatabaseConnection.h>
#import <YapDatabase/YapDatabaseTransaction.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -152,9 +153,9 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
- (void)updateCallType:(RPRecentCallType)callType
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateCallType:callType transaction:transaction];
}];
} error:nil];
}
- (void)updateCallType:(RPRecentCallType)callType transaction:(YapDatabaseReadWriteTransaction *)transaction

View file

@ -241,7 +241,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
}
}
dbConnection.readWrite { (transaction) in
try! Storage.writeSync { (transaction) in
let oldMode = self.unidentifiedAccessMode(forRecipientId: recipientId, isLocalNumber: isLocalNumber, transaction: transaction)
transaction.setObject(mode.rawValue as Int, forKey: recipientId, inCollection: self.kUnidentifiedAccessCollection)

View file

@ -51,11 +51,11 @@ public class MessageSenderJobQueue: NSObject, JobQueue {
inMessage: mediaMessage,
completionHandler: { error in
if let error = error {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
mediaMessage.update(sendingError: error, transaction: transaction)
}
} else {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.add(message: mediaMessage, removeMessageAfterSending: isTemporaryAttachment, transaction: transaction)
}
}
@ -96,7 +96,7 @@ public class MessageSenderJobQueue: NSObject, JobQueue {
/// Used when the user clears their database to cancel any outstanding jobs.
@objc public func clearAllJobs() {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
let statuses: [SSKJobRecordStatus] = [ .unknown, .ready, .running, .permanentlyFailed ]
var records: [SSKJobRecord] = []
statuses.forEach {
@ -196,7 +196,7 @@ public class MessageSenderOperation: OWSOperation, DurableOperation {
}
override public func didSucceed() {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperationDidSucceed(self, transaction: transaction)
if self.jobRecord.removeMessageAfterSending {
self.message.remove(with: transaction)
@ -205,7 +205,7 @@ public class MessageSenderOperation: OWSOperation, DurableOperation {
}
override public func didReportError(_ error: Error) {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperation(self, didReportError: error, transaction: transaction)
}
}
@ -227,7 +227,7 @@ public class MessageSenderOperation: OWSOperation, DurableOperation {
}
override public func didFail(error: Error) {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperation(self, didFailWithError: error, transaction: transaction)
self.message.update(sendingError: error, transaction: transaction)

View file

@ -795,12 +795,11 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
}
if (!success) {
[[self.primaryStorage newDatabaseConnection]
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage corruptedMessageInUnknownThread];
[self.notificationsManager notifyUserForThreadlessErrorMessage:errorMessage
transaction:transaction];
}];
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSErrorMessage *errorMessage = [TSErrorMessage corruptedMessageInUnknownThread];
[self.notificationsManager notifyUserForThreadlessErrorMessage:errorMessage
transaction:transaction];
} error:nil];
}
dispatch_async(dispatch_get_main_queue(), ^{

View file

@ -149,7 +149,7 @@ SSKProtoVerified *_Nullable BuildVerifiedProtoWithRecipientId(NSString *destinat
{
changeBlock(self);
[[self class].dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
OWSRecipientIdentity *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId transaction:transaction];
if (latest == nil) {
[self saveWithTransaction:transaction];
@ -158,7 +158,7 @@ SSKProtoVerified *_Nullable BuildVerifiedProtoWithRecipientId(NSString *destinat
changeBlock(latest);
[latest saveWithTransaction:transaction];
}];
} error:nil];
}
#pragma mark - debug

View file

@ -452,7 +452,7 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
// made in another process (e.g. the SAE) from showing up in other processes.
// There's a simple workaround: a trivial write to the database flushes changes
// made from other processes.
[self.dbReadWriteConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:[NSUUID UUID].UUIDString forKey:@"conversation_view_noop_mod" inCollection:@"temp"];
}];
}

View file

@ -6,6 +6,7 @@
#import "OWSPrimaryStorage.h"
#import "SSKEnvironment.h"
#import <YapDatabase/YapDatabaseTransaction.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -45,17 +46,16 @@ NS_ASSUME_NONNULL_BEGIN
- (void)save
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self saveWithTransaction:transaction];
}];
} error:nil];
}
- (void)saveAsyncWithCompletionBlock:(void (^_Nullable)(void))completionBlock
{
[[self dbReadWriteConnection] asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self saveWithTransaction:transaction];
}
completionBlock:completionBlock];
} completion:completionBlock];
}
- (void)touchWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
@ -65,9 +65,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)touch
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self touchWithTransaction:transaction];
}];
} error:nil];
}
- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
@ -77,9 +77,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)remove
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self removeWithTransaction:transaction];
}];
} error:nil];
}
- (YapDatabaseConnection *)dbReadConnection
@ -181,9 +181,9 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)removeAllObjectsInCollection
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:[self collection]];
}];
} error:nil];
}
+ (nullable instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID

View file

@ -157,7 +157,7 @@ public extension JobQueue {
return
}
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
guard let nextJob: JobRecordType = self.finder.getNextReady(label: self.jobRecordLabel, transaction: transaction) as? JobRecordType else {
Logger.verbose("nothing left to enqueue")
return
@ -197,7 +197,7 @@ public extension JobQueue {
}
public func restartOldJobs() {
self.dbConnection.readWrite { transaction in
try! Storage.writeSync { transaction in
let runningRecords = self.finder.allRecords(label: self.jobRecordLabel, status: .running, transaction: transaction)
Logger.info("marking old `running` JobRecords as ready: \(runningRecords.count)")
for record in runningRecords {

View file

@ -13,6 +13,7 @@
#import <Reachability/Reachability.h>
#import <SessionCoreKit/Cryptography.h>
#import <YapDatabase/YapDatabase.h>
#import <SessionServiceKit/SessionServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -187,10 +188,10 @@ NSString *NSStringForOWSAnalyticsSeverity(OWSAnalyticsSeverity severity)
dispatch_async(self.serialQueue, ^{
self.hasRequestInFlight = NO;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Remove from queue.
[transaction removeObjectForKey:eventKey inCollection:kOWSAnalytics_EventsCollection];
}];
} error:nil];
// Wait a second between network requests / retries.
dispatch_after(
@ -323,7 +324,7 @@ NSString *NSStringForOWSAnalyticsSeverity(OWSAnalyticsSeverity severity)
[self sendEvent:eventDictionary eventKey:eventKey isCritical:YES];
} else {
// Add to queue.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
const int kMaxQueuedEvents = 5000;
if ([transaction numberOfKeysInCollection:kOWSAnalytics_EventsCollection] > kMaxQueuedEvents) {
OWSLogError(@"Event queue overflow.");
@ -331,7 +332,7 @@ NSString *NSStringForOWSAnalyticsSeverity(OWSAnalyticsSeverity severity)
}
[transaction setObject:eventDictionary forKey:eventKey inCollection:kOWSAnalytics_EventsCollection];
}];
} error:nil];
[self tryToSyncEvents];
}