From a14b2c0960e69f1328855e5a590f5003017ceaa5 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 15 Dec 2022 15:20:59 +1100 Subject: [PATCH 1/7] fix an issue where open group messages over 6 months old won't actually be trimmed --- SessionMessagingKit/Jobs/Types/GarbageCollectionJob.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SessionMessagingKit/Jobs/Types/GarbageCollectionJob.swift b/SessionMessagingKit/Jobs/Types/GarbageCollectionJob.swift index 6c47e876f..e8d50e5c2 100644 --- a/SessionMessagingKit/Jobs/Types/GarbageCollectionJob.swift +++ b/SessionMessagingKit/Jobs/Types/GarbageCollectionJob.swift @@ -96,7 +96,7 @@ public enum GarbageCollectionJob: JobExecutor { GROUP BY \(interaction[.threadId]) ) AS interactionInfo ON interactionInfo.\(threadIdLiteral) = \(interaction[.threadId]) WHERE ( - \(interaction[.timestampMs]) < \(timestampNow - approxSixMonthsInSeconds) AND + \(interaction[.timestampMs]) < \((timestampNow - approxSixMonthsInSeconds) * 1000) AND interactionInfo.interactionCount >= \(minInteractionsToTrimSql) ) ) From 751eb8ce66b0ab5e3544fab4f5f118d553c56d94 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 15 Dec 2022 15:23:41 +1100 Subject: [PATCH 2/7] fix an issue where linking a device will remove the username on main device --- SessionMessagingKit/Sending & Receiving/MessageReceiver.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index f3b6f674c..ec3e7dff1 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -318,7 +318,7 @@ public enum MessageReceiver { var updatedProfile: Profile = profile // Name - if let name = name, name != profile.name { + if let name = name, !name.isEmpty, name != profile.name { let shouldUpdate: Bool if isCurrentUser { shouldUpdate = given(UserDefaults.standard[.lastDisplayNameUpdate]) { From c867c95c7a80b7f9fdcd827f6c7803e8c73d198c Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 15 Dec 2022 15:48:06 +1100 Subject: [PATCH 3/7] fix a crash happening when long mnemonic is used to recover an account --- Session/Onboarding/RestoreVC.swift | 2 +- SessionUtilitiesKit/Database/Models/Identity.swift | 2 +- SessionUtilitiesKit/General/General.swift | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Session/Onboarding/RestoreVC.swift b/Session/Onboarding/RestoreVC.swift index 0e6496757..5fbf82436 100644 --- a/Session/Onboarding/RestoreVC.swift +++ b/Session/Onboarding/RestoreVC.swift @@ -198,7 +198,7 @@ final class RestoreVC: BaseVC { do { let hexEncodedSeed = try Mnemonic.decode(mnemonic: mnemonic) let seed = Data(hex: hexEncodedSeed) - let (ed25519KeyPair, x25519KeyPair) = try! Identity.generate(from: seed) + let (ed25519KeyPair, x25519KeyPair) = try Identity.generate(from: seed) Onboarding.Flow.recover.preregister(with: seed, ed25519KeyPair: ed25519KeyPair, x25519KeyPair: x25519KeyPair) mnemonicTextView.resignFirstResponder() diff --git a/SessionUtilitiesKit/Database/Models/Identity.swift b/SessionUtilitiesKit/Database/Models/Identity.swift index 9d08731f5..4f3f82ee8 100644 --- a/SessionUtilitiesKit/Database/Models/Identity.swift +++ b/SessionUtilitiesKit/Database/Models/Identity.swift @@ -53,7 +53,7 @@ extension ECKeyPair { public extension Identity { static func generate(from seed: Data) throws -> (ed25519KeyPair: Sign.KeyPair, x25519KeyPair: ECKeyPair) { - assert(seed.count == 16) + guard (seed.count == 16) else { throw GeneralError.invalidSeed } let padding = Data(repeating: 0, count: 16) guard diff --git a/SessionUtilitiesKit/General/General.swift b/SessionUtilitiesKit/General/General.swift index 714184ee3..72576fb56 100644 --- a/SessionUtilitiesKit/General/General.swift +++ b/SessionUtilitiesKit/General/General.swift @@ -19,6 +19,7 @@ public enum General { } public enum GeneralError: Error { + case invalidSeed case keyGenerationFailed } From c78409a2d6d671d19c37ac0be3a8676b894824f5 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 21 Dec 2022 09:10:47 +1100 Subject: [PATCH 4/7] Increased the file upload size to 10Mb Removed the 'fileSizeORMultiplier' that was dealing with the b64 encoding (no longer exists) Increased the request timeout for file upload/download to 30 seconds (up from 10 seconds) --- .../Database/Models/Attachment.swift | 2 +- .../File Server/FileServerAPI.swift | 12 ++++------ .../Open Groups/OpenGroupAPI.swift | 5 +++- SessionSnodeKit/OnionRequestAPI.swift | 24 +++++++++++-------- SignalUtilitiesKit/Configuration.swift | 5 +--- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/SessionMessagingKit/Database/Models/Attachment.swift b/SessionMessagingKit/Database/Models/Attachment.swift index a62849bd7..21b79540c 100644 --- a/SessionMessagingKit/Database/Models/Attachment.swift +++ b/SessionMessagingKit/Database/Models/Attachment.swift @@ -1062,7 +1062,7 @@ extension Attachment { // Check the file size SNLog("File size: \(data.count) bytes.") - if Double(data.count) > Double(FileServerAPI.maxFileSize) / FileServerAPI.fileSizeORMultiplier { + if data.count > FileServerAPI.maxFileSize { failure?(HTTP.Error.maxFileSizeExceeded) return } diff --git a/SessionMessagingKit/File Server/FileServerAPI.swift b/SessionMessagingKit/File Server/FileServerAPI.swift index 694bf53be..065a8b94c 100644 --- a/SessionMessagingKit/File Server/FileServerAPI.swift +++ b/SessionMessagingKit/File Server/FileServerAPI.swift @@ -15,13 +15,9 @@ public final class FileServerAPI: NSObject { @objc public static let server = "http://filev2.getsession.org" public static let serverPublicKey = "da21e1d886c6fbaea313f75298bd64aab03a97ce985b46bb2dad9f2089c8ee59" public static let maxFileSize = (10 * 1024 * 1024) // 10 MB - /// The file server has a file size limit of `maxFileSize`, which the Service Nodes try to enforce as well. However, the limit applied by the Service Nodes - /// is on the **HTTP request** and not the actual file size. Because the file server expects the file data to be base 64 encoded, the size of the HTTP - /// request for a given file will be at least `ceil(n / 3) * 4` bytes, where n is the file size in bytes. This is the minimum size because there might also - /// be other parameters in the request. On average the multiplier appears to be about 1.5, so when checking whether the file will exceed the file size limit when - /// uploading a file we just divide the size of the file by this number. The alternative would be to actually check the size of the HTTP request but that's only - /// possible after proof of work has been calculated and the onion request encryption has happened, which takes several seconds. - public static let fileSizeORMultiplier: Double = 2 + + /// Standard timeout is 10 seconds which is a little too short fir file upload/download with slightly larger files + public static let fileTimeout: TimeInterval = 30 // MARK: - File Storage @@ -77,7 +73,7 @@ public final class FileServerAPI: NSObject { return Promise(error: error) } - return OnionRequestAPI.sendOnionRequest(urlRequest, to: request.server, with: serverPublicKey) + return OnionRequestAPI.sendOnionRequest(urlRequest, to: request.server, with: serverPublicKey, timeout: FileServerAPI.fileTimeout) .map2 { _, response in guard let response: Data = response else { throw HTTP.Error.parsingFailed } diff --git a/SessionMessagingKit/Open Groups/OpenGroupAPI.swift b/SessionMessagingKit/Open Groups/OpenGroupAPI.swift index 051ba7cc2..9b4984627 100644 --- a/SessionMessagingKit/Open Groups/OpenGroupAPI.swift +++ b/SessionMessagingKit/Open Groups/OpenGroupAPI.swift @@ -871,6 +871,7 @@ public enum OpenGroupAPI { ], body: bytes ), + timeout: FileServerAPI.fileTimeout, using: dependencies ) .decoded(as: FileUploadResponse.self, on: OpenGroupAPI.workQueue, using: dependencies) @@ -890,6 +891,7 @@ public enum OpenGroupAPI { server: server, endpoint: .roomFileIndividual(roomToken, fileId) ), + timeout: FileServerAPI.fileTimeout, using: dependencies ) .map { responseInfo, maybeData in @@ -1391,6 +1393,7 @@ public enum OpenGroupAPI { _ db: Database, request: Request, forceBlinded: Bool = false, + timeout: TimeInterval = HTTP.timeout, using dependencies: SMKDependencies = SMKDependencies() ) -> Promise<(OnionRequestResponseInfoType, Data?)> { let urlRequest: URLRequest @@ -1415,6 +1418,6 @@ public enum OpenGroupAPI { return Promise(error: OpenGroupAPIError.signingFailed) } - return dependencies.onionApi.sendOnionRequest(signedRequest, to: request.server, with: publicKey) + return dependencies.onionApi.sendOnionRequest(signedRequest, to: request.server, with: publicKey, timeout: timeout) } } diff --git a/SessionSnodeKit/OnionRequestAPI.swift b/SessionSnodeKit/OnionRequestAPI.swift index d2a71b66c..2254c160e 100644 --- a/SessionSnodeKit/OnionRequestAPI.swift +++ b/SessionSnodeKit/OnionRequestAPI.swift @@ -7,13 +7,17 @@ import PromiseKit import SessionUtilitiesKit public protocol OnionRequestAPIType { - static func sendOnionRequest(to snode: Snode, invoking method: SnodeAPIEndpoint, with parameters: JSON, associatedWith publicKey: String?) -> Promise - static func sendOnionRequest(_ request: URLRequest, to server: String, using version: OnionRequestAPIVersion, with x25519PublicKey: String) -> Promise<(OnionRequestResponseInfoType, Data?)> + static func sendOnionRequest(to snode: Snode, invoking method: SnodeAPIEndpoint, with parameters: JSON, associatedWith publicKey: String?, timeout: TimeInterval) -> Promise + static func sendOnionRequest(_ request: URLRequest, to server: String, using version: OnionRequestAPIVersion, with x25519PublicKey: String, timeout: TimeInterval) -> Promise<(OnionRequestResponseInfoType, Data?)> } public extension OnionRequestAPIType { - static func sendOnionRequest(_ request: URLRequest, to server: String, with x25519PublicKey: String) -> Promise<(OnionRequestResponseInfoType, Data?)> { - sendOnionRequest(request, to: server, using: .v4, with: x25519PublicKey) + static func sendOnionRequest(to snode: Snode, invoking method: SnodeAPIEndpoint, with parameters: JSON, associatedWith publicKey: String?) -> Promise { + sendOnionRequest(to: snode, invoking: method, with: parameters, associatedWith: publicKey, timeout: HTTP.timeout) + } + + static func sendOnionRequest(_ request: URLRequest, to server: String, with x25519PublicKey: String, timeout: TimeInterval = HTTP.timeout) -> Promise<(OnionRequestResponseInfoType, Data?)> { + sendOnionRequest(request, to: server, using: .v4, with: x25519PublicKey, timeout: timeout) } } @@ -369,7 +373,7 @@ public enum OnionRequestAPI: OnionRequestAPIType { // MARK: - Public API /// Sends an onion request to `snode`. Builds new paths as needed. - public static func sendOnionRequest(to snode: Snode, invoking method: SnodeAPIEndpoint, with parameters: JSON, associatedWith publicKey: String? = nil) -> Promise { + public static func sendOnionRequest(to snode: Snode, invoking method: SnodeAPIEndpoint, with parameters: JSON, associatedWith publicKey: String? = nil, timeout: TimeInterval = HTTP.timeout) -> Promise { let payloadJson: JSON = [ "method" : method.rawValue, "params" : parameters ] guard let payload: Data = try? JSONSerialization.data(withJSONObject: payloadJson, options: []) else { @@ -377,7 +381,7 @@ public enum OnionRequestAPI: OnionRequestAPIType { } /// **Note:** Currently the service nodes only support V3 Onion Requests - return sendOnionRequest(with: payload, to: OnionRequestAPIDestination.snode(snode), version: .v3) + return sendOnionRequest(with: payload, to: OnionRequestAPIDestination.snode(snode), version: .v3, timeout: timeout) .map { _, maybeData in guard let data: Data = maybeData else { throw HTTP.Error.invalidResponse } @@ -393,7 +397,7 @@ public enum OnionRequestAPI: OnionRequestAPIType { } /// Sends an onion request to `server`. Builds new paths as needed. - public static func sendOnionRequest(_ request: URLRequest, to server: String, using version: OnionRequestAPIVersion = .v4, with x25519PublicKey: String) -> Promise<(OnionRequestResponseInfoType, Data?)> { + public static func sendOnionRequest(_ request: URLRequest, to server: String, using version: OnionRequestAPIVersion = .v4, with x25519PublicKey: String, timeout: TimeInterval = HTTP.timeout) -> Promise<(OnionRequestResponseInfoType, Data?)> { guard let url = request.url, let host = request.url?.host else { return Promise(error: OnionRequestAPIError.invalidURL) } @@ -412,14 +416,14 @@ public enum OnionRequestAPI: OnionRequestAPIType { scheme: scheme, port: port ) - let promise = sendOnionRequest(with: payload, to: destination, version: version) + let promise = sendOnionRequest(with: payload, to: destination, version: version, timeout: timeout) promise.catch2 { error in SNLog("Couldn't reach server: \(url) due to error: \(error).") } return promise } - public static func sendOnionRequest(with payload: Data, to destination: OnionRequestAPIDestination, version: OnionRequestAPIVersion) -> Promise<(OnionRequestResponseInfoType, Data?)> { + public static func sendOnionRequest(with payload: Data, to destination: OnionRequestAPIDestination, version: OnionRequestAPIVersion, timeout: TimeInterval = HTTP.timeout) -> Promise<(OnionRequestResponseInfoType, Data?)> { let (promise, seal) = Promise<(OnionRequestResponseInfoType, Data?)>.pending() var guardSnode: Snode? @@ -444,7 +448,7 @@ public enum OnionRequestAPI: OnionRequestAPIType { } let destinationSymmetricKey = intermediate.destinationSymmetricKey - HTTP.execute(.post, url, body: body) + HTTP.execute(.post, url, body: body, timeout: timeout) .done2 { responseData in handleResponse( responseData: responseData, diff --git a/SignalUtilitiesKit/Configuration.swift b/SignalUtilitiesKit/Configuration.swift index 2c0414db2..4ab7e2d50 100644 --- a/SignalUtilitiesKit/Configuration.swift +++ b/SignalUtilitiesKit/Configuration.swift @@ -8,10 +8,7 @@ import SessionMessagingKit public enum Configuration { public static func performMainSetup() { // Need to do this first to ensure the legacy database exists - SNUtilitiesKit.configure( - maxFileSize: UInt(Double(FileServerAPI.maxFileSize) / FileServerAPI.fileSizeORMultiplier) - ) - + SNUtilitiesKit.configure(maxFileSize: UInt(FileServerAPI.maxFileSize)) SNMessagingKit.configure() SNSnodeKit.configure() SNUIKit.configure() From f7199b4c4480a90b9b375c8c311d404f3b1f7588 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 21 Dec 2022 16:39:52 +1100 Subject: [PATCH 5/7] Updated the code to take the service node offset into account when setting timestamps --- Session/Calls/Call Management/SessionCall.swift | 2 +- .../ConversationVC+Interaction.swift | 12 ++++++------ .../ThreadDisappearingMessagesViewModel.swift | 2 +- .../Settings/ThreadSettingsViewModel.swift | 2 +- Session/Notifications/AppNotifications.swift | 2 +- SessionMessagingKit/Calls/WebRTCSession.swift | 3 ++- .../Migrations/_003_YDBToGRDBMigration.swift | 4 ++-- .../Database/Models/Attachment.swift | 7 ++++--- .../Models/ControlMessageProcessRecord.swift | 9 +++++++-- .../DisappearingMessageConfiguration.swift | 3 ++- .../Database/Models/Interaction.swift | 5 +++-- .../Database/Models/LinkPreview.swift | 3 ++- .../Database/Models/SessionThread.swift | 3 ++- .../Jobs/Types/AttachmentDownloadJob.swift | 2 +- .../Jobs/Types/DisappearingMessagesJob.swift | 3 ++- SessionMessagingKit/Messages/Message.swift | 12 +++++++++--- .../MessageReceiver+Calls.swift | 5 +++-- .../MessageReceiver+ClosedGroups.swift | 13 +++++++------ ...ageReceiver+DataExtractionNotification.swift | 3 ++- .../MessageReceiver+MessageRequests.swift | 3 ++- .../MessageSender+ClosedGroups.swift | 17 +++++++++-------- .../Sending & Receiving/MessageReceiver.swift | 3 ++- .../Sending & Receiving/MessageSender.swift | 13 ++++++++----- .../Typing Indicators/TypingIndicators.swift | 3 ++- SessionShareExtension/ThreadPickerVC.swift | 2 +- .../Models/SnodeReceivedMessageInfo.swift | 4 ++-- SessionSnodeKit/SnodeAPI.swift | 12 ++++++++++-- 27 files changed, 94 insertions(+), 58 deletions(-) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index 1fc8620a5..a9ccbcdf0 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -206,7 +206,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { let thread: SessionThread = try? SessionThread.fetchOne(db, id: sessionId) else { return } - let timestampMs: Int64 = Int64(floor(Date().timeIntervalSince1970 * 1000)) + let timestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs() let message: CallMessage = CallMessage( uuid: self.uuid, kind: .preOffer, diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 83cbbb45a..7758c398e 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -409,7 +409,7 @@ extension ConversationVC: // flags appropriately let threadId: String = self.viewModel.threadData.threadId let oldThreadShouldBeVisible: Bool = (self.viewModel.threadData.threadShouldBeVisible == true) - let sentTimestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000))) + let sentTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs() let linkPreviewDraft: LinkPreviewDraft? = snInputView.linkPreviewInfo?.draft let quoteModel: QuotedReplyModel? = snInputView.quoteDraftInfo?.model @@ -534,7 +534,7 @@ extension ConversationVC: // flags appropriately let threadId: String = self.viewModel.threadData.threadId let oldThreadShouldBeVisible: Bool = (self.viewModel.threadData.threadShouldBeVisible == true) - let sentTimestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000))) + let sentTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs() // If this was a message request then approve it approveMessageRequestIfNeeded( @@ -640,7 +640,7 @@ extension ConversationVC: threadVariant: threadVariant, threadIsMessageRequest: threadIsMessageRequest, direction: .outgoing, - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ) if needsToStartTypingIndicator { @@ -1219,7 +1219,7 @@ extension ConversationVC: guard !threadIsMessageRequest else { return } // Perform local rate limiting (don't allow more than 20 reactions within 60 seconds) - let sentTimestamp: Int64 = Int64(floor(Date().timeIntervalSince1970 * 1000)) + let sentTimestamp: Int64 = SnodeAPI.currentOffsetTimestampMs() let recentReactionTimestamps: [Int64] = General.cache.wrappedValue.recentReactionTimestamps guard @@ -2044,7 +2044,7 @@ extension ConversationVC: // Create URL let directory: String = OWSTemporaryDirectory() - let fileName: String = "\(Int64(floor(Date().timeIntervalSince1970 * 1000))).m4a" + let fileName: String = "\(SnodeAPI.currentOffsetTimestampMs()).m4a" let url: URL = URL(fileURLWithPath: directory).appendingPathComponent(fileName) // Set up audio session @@ -2285,7 +2285,7 @@ extension ConversationVC { for: self.viewModel.threadData.threadId, threadVariant: self.viewModel.threadData.threadVariant, isNewThread: false, - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ) } diff --git a/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift b/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift index aace471aa..886cc326a 100644 --- a/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift +++ b/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift @@ -168,7 +168,7 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel () ) { // The 'backgroundTask' gets captured and cleared within the 'completion' block - let timestampNowMs: TimeInterval = ceil(Date().timeIntervalSince1970 * 1000) + let timestampNowMs: TimeInterval = TimeInterval(SnodeAPI.currentOffsetTimestampMs()) var backgroundTask: OWSBackgroundTask? = OWSBackgroundTask(label: #function) let updatedJob: Job? = Storage.shared.write { db in diff --git a/SessionMessagingKit/Messages/Message.swift b/SessionMessagingKit/Messages/Message.swift index bac6dbb5e..1f239920c 100644 --- a/SessionMessagingKit/Messages/Message.swift +++ b/SessionMessagingKit/Messages/Message.swift @@ -259,7 +259,10 @@ public extension Message { return try processRawReceivedMessage( db, envelope: envelope, - serverExpirationTimestamp: (Date().timeIntervalSince1970 + ControlMessageProcessRecord.defaultExpirationSeconds), + serverExpirationTimestamp: ( + (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) + + ControlMessageProcessRecord.defaultExpirationSeconds + ), serverHash: serverHash, handleClosedGroupKeyUpdateMessages: true ) @@ -275,7 +278,10 @@ public extension Message { let processedMessage: ProcessedMessage? = try processRawReceivedMessage( db, envelope: envelope, - serverExpirationTimestamp: (Date().timeIntervalSince1970 + ControlMessageProcessRecord.defaultExpirationSeconds), + serverExpirationTimestamp: ( + (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) + + ControlMessageProcessRecord.defaultExpirationSeconds + ), serverHash: nil, handleClosedGroupKeyUpdateMessages: false ) @@ -407,7 +413,7 @@ public extension Message { let count: Int64 = rawReaction.you ? rawReaction.count - 1 : rawReaction.count - let timestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000))) + let timestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs() let maxLength: Int = shouldAddSelfReaction ? 4 : 5 let desiredReactorIds: [String] = reactors .filter { $0 != blindedUserPublicKey && $0 != userPublicKey } // Remove current user for now, will add back if needed diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift index 8dc60c126..9f8f652db 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+Calls.swift @@ -4,6 +4,7 @@ import Foundation import GRDB import WebRTC import SessionUtilitiesKit +import SessionSnodeKit extension MessageReceiver { public static func handleCallMessage(_ db: Database, message: CallMessage) throws { @@ -189,7 +190,7 @@ extension MessageReceiver { body: String(data: messageInfoData, encoding: .utf8), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ) .inserted(db) @@ -235,7 +236,7 @@ extension MessageReceiver { ) let timestampMs: Int64 = ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) guard let messageInfoData: Data = try? JSONEncoder().encode(messageInfo) else { return nil } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift index 5c5620a81..669e46de0 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift @@ -4,6 +4,7 @@ import Foundation import GRDB import Sodium import SessionUtilitiesKit +import SessionSnodeKit extension MessageReceiver { public static func handleClosedGroupControlMessage(_ db: Database, _ message: ClosedGroupControlMessage) throws { @@ -135,7 +136,7 @@ extension MessageReceiver { threadId: groupPublicKey, publicKey: Data(encryptionKeyPair.publicKey), secretKey: Data(encryptionKeyPair.secretKey), - receivedTimestamp: Date().timeIntervalSince1970 + receivedTimestamp: (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) ).insert(db) // Start polling @@ -196,7 +197,7 @@ extension MessageReceiver { threadId: groupPublicKey, publicKey: proto.publicKey.removingIdPrefixIfNeeded(), secretKey: proto.privateKey, - receivedTimestamp: Date().timeIntervalSince1970 + receivedTimestamp: (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) ).insert(db) } catch { @@ -231,7 +232,7 @@ extension MessageReceiver { .infoMessage(db, sender: sender), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } @@ -307,7 +308,7 @@ extension MessageReceiver { .infoMessage(db, sender: sender), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } @@ -383,7 +384,7 @@ extension MessageReceiver { .infoMessage(db, sender: sender), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } @@ -461,7 +462,7 @@ extension MessageReceiver { .infoMessage(db, sender: sender), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift index fd74915a9..a28346f6d 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+DataExtractionNotification.swift @@ -2,6 +2,7 @@ import Foundation import GRDB +import SessionSnodeKit extension MessageReceiver { internal static func handleDataExtractionNotification(_ db: Database, message: DataExtractionNotification) throws { @@ -24,7 +25,7 @@ extension MessageReceiver { }(), timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+MessageRequests.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+MessageRequests.swift index d16adbe95..06ee54eb3 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+MessageRequests.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+MessageRequests.swift @@ -4,6 +4,7 @@ import Foundation import GRDB import SignalCoreKit import SessionUtilitiesKit +import SessionSnodeKit extension MessageReceiver { internal static func handleMessageRequestResponse( @@ -123,7 +124,7 @@ extension MessageReceiver { variant: .infoMessageRequestAccepted, timestampMs: ( message.sentTimestamp.map { Int64($0) } ?? - Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.currentOffsetTimestampMs() ) ).inserted(db) } diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift index bc8d52a0b..0d219b5b2 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift @@ -6,6 +6,7 @@ import Sodium import Curve25519Kit import PromiseKit import SessionUtilitiesKit +import SessionSnodeKit extension MessageSender { public static var distributingKeyPairs: Atomic<[String: [ClosedGroupKeyPair]]> = Atomic([:]) @@ -24,7 +25,7 @@ extension MessageSender { let membersAsData = members.map { Data(hex: $0) } let admins = [ userPublicKey ] let adminsAsData = admins.map { Data(hex: $0) } - let formationTimestamp: TimeInterval = Date().timeIntervalSince1970 + let formationTimestamp: TimeInterval = (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) let thread: SessionThread = try SessionThread .fetchOrCreate(db, id: groupPublicKey, variant: .closedGroup) try ClosedGroup( @@ -91,7 +92,7 @@ extension MessageSender { threadId: groupPublicKey, publicKey: encryptionKeyPair.publicKey, secretKey: encryptionKeyPair.privateKey, - receivedTimestamp: Date().timeIntervalSince1970 + receivedTimestamp: (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) ).insert(db) // Notify the PN server @@ -110,7 +111,7 @@ extension MessageSender { threadId: thread.id, authorId: userPublicKey, variant: .infoClosedGroupCreated, - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ).inserted(db) // Start polling @@ -142,7 +143,7 @@ extension MessageSender { threadId: closedGroup.threadId, publicKey: legacyNewKeyPair.publicKey, secretKey: legacyNewKeyPair.privateKey, - receivedTimestamp: Date().timeIntervalSince1970 + receivedTimestamp: (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) ) // Distribute it @@ -230,7 +231,7 @@ extension MessageSender { body: ClosedGroupControlMessage.Kind .nameChange(name: name) .infoMessage(db, sender: userPublicKey), - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ).inserted(db) guard let interactionId: Int64 = interaction.id else { throw StorageError.objectNotSaved } @@ -330,7 +331,7 @@ extension MessageSender { body: ClosedGroupControlMessage.Kind .membersAdded(members: addedMembers.map { Data(hex: $0) }) .infoMessage(db, sender: userPublicKey), - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ).inserted(db) guard let interactionId: Int64 = interaction.id else { throw StorageError.objectNotSaved } @@ -431,7 +432,7 @@ extension MessageSender { body: ClosedGroupControlMessage.Kind .membersRemoved(members: removedMembers.map { Data(hex: $0) }) .infoMessage(db, sender: userPublicKey), - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ).inserted(db) guard let newInteractionId: Int64 = interaction.id else { throw StorageError.objectNotSaved } @@ -496,7 +497,7 @@ extension MessageSender { body: ClosedGroupControlMessage.Kind .memberLeft .infoMessage(db, sender: userPublicKey), - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)) + timestampMs: SnodeAPI.currentOffsetTimestampMs() ).inserted(db) guard let interactionId: Int64 = interaction.id else { diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index f3b6f674c..88b9d4ea2 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -5,6 +5,7 @@ import GRDB import Sodium import SignalCoreKit import SessionUtilitiesKit +import SessionSnodeKit public enum MessageReceiver { private static var lastEncryptionKeyPairRequest: [String: Date] = [:] @@ -144,7 +145,7 @@ public enum MessageReceiver { message.sender = sender message.recipient = userPublicKey message.sentTimestamp = envelope.timestamp - message.receivedTimestamp = UInt64((Date().timeIntervalSince1970) * 1000) + message.receivedTimestamp = SnodeAPI.currentTimestampMs() message.groupPublicKey = groupPublicKey message.openGroupServerMessageId = openGroupMessageServerId.map { UInt64($0) } diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 547ab9521..297e70732 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -67,7 +67,7 @@ public final class MessageSender { let (promise, seal) = Promise.pending() let userPublicKey: String = getUserHexEncodedPublicKey(db) let isMainAppActive: Bool = (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) - let messageSendTimestamp: Int64 = Int64(floor(Date().timeIntervalSince1970 * 1000)) + let messageSendTimestamp: Int64 = SnodeAPI.currentOffsetTimestampMs() // Set the timestamp, sender and recipient message.sentTimestamp = ( @@ -322,7 +322,7 @@ public final class MessageSender { // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set - message.sentTimestamp = UInt64(floor(Date().timeIntervalSince1970 * 1000)) + message.sentTimestamp = SnodeAPI.currentTimestampMs() } switch destination { @@ -472,7 +472,7 @@ public final class MessageSender { // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set - message.sentTimestamp = UInt64(floor(Date().timeIntervalSince1970 * 1000)) + message.sentTimestamp = SnodeAPI.currentTimestampMs() } message.sender = userPublicKey @@ -617,7 +617,7 @@ public final class MessageSender { job: DisappearingMessagesJob.updateNextRunIfNeeded( db, interaction: interaction, - startedAtMs: (Date().timeIntervalSince1970 * 1000) + startedAtMs: TimeInterval(SnodeAPI.currentOffsetTimestampMs()) ) ) } @@ -636,7 +636,10 @@ public final class MessageSender { } }(), message: message, - serverExpirationTimestamp: (Date().timeIntervalSince1970 + ControlMessageProcessRecord.defaultExpirationSeconds) + serverExpirationTimestamp: ( + (TimeInterval(SnodeAPI.currentOffsetTimestampMs()) / 1000) + + ControlMessageProcessRecord.defaultExpirationSeconds + ) )?.insert(db) // Sync the message if: diff --git a/SessionMessagingKit/Sending & Receiving/Typing Indicators/TypingIndicators.swift b/SessionMessagingKit/Sending & Receiving/Typing Indicators/TypingIndicators.swift index 9e50e80b8..afebe2c10 100644 --- a/SessionMessagingKit/Sending & Receiving/Typing Indicators/TypingIndicators.swift +++ b/SessionMessagingKit/Sending & Receiving/Typing Indicators/TypingIndicators.swift @@ -3,6 +3,7 @@ import Foundation import GRDB import SessionUtilitiesKit +import SessionSnodeKit public class TypingIndicators { // MARK: - Direction @@ -41,7 +42,7 @@ public class TypingIndicators { self.threadId = threadId self.direction = direction - self.timestampMs = (timestampMs ?? Int64(floor(Date().timeIntervalSince1970 * 1000))) + self.timestampMs = (timestampMs ?? SnodeAPI.currentOffsetTimestampMs()) } fileprivate func start(_ db: Database) { diff --git a/SessionShareExtension/ThreadPickerVC.swift b/SessionShareExtension/ThreadPickerVC.swift index 7db42407d..5fb7aaf2a 100644 --- a/SessionShareExtension/ThreadPickerVC.swift +++ b/SessionShareExtension/ThreadPickerVC.swift @@ -196,7 +196,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView authorId: getUserHexEncodedPublicKey(db), variant: .standardOutgoing, body: body, - timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)), + timestampMs: SnodeAPI.currentOffsetTimestampMs(), hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: body), expiresInSeconds: try? DisappearingMessagesConfiguration .select(.durationSeconds) diff --git a/SessionSnodeKit/Database/Models/SnodeReceivedMessageInfo.swift b/SessionSnodeKit/Database/Models/SnodeReceivedMessageInfo.swift index 7addb56e5..336a19de8 100644 --- a/SessionSnodeKit/Database/Models/SnodeReceivedMessageInfo.swift +++ b/SessionSnodeKit/Database/Models/SnodeReceivedMessageInfo.swift @@ -93,7 +93,7 @@ public extension SnodeReceivedMessageInfo { return try SnodeReceivedMessageInfo .select(Column.rowID) .filter(SnodeReceivedMessageInfo.Columns.key == key(for: snode, publicKey: publicKey, namespace: namespace)) - .filter(SnodeReceivedMessageInfo.Columns.expirationDateMs <= (Date().timeIntervalSince1970 * 1000)) + .filter(SnodeReceivedMessageInfo.Columns.expirationDateMs <= SnodeAPI.currentOffsetTimestampMs()) .asRequest(of: Int64.self) .fetchAll(db) } @@ -122,7 +122,7 @@ public extension SnodeReceivedMessageInfo { SnodeReceivedMessageInfo.Columns.wasDeletedOrInvalid == false ) .filter(SnodeReceivedMessageInfo.Columns.key == key(for: snode, publicKey: publicKey, namespace: namespace)) - .filter(SnodeReceivedMessageInfo.Columns.expirationDateMs > (Date().timeIntervalSince1970 * 1000)) + .filter(SnodeReceivedMessageInfo.Columns.expirationDateMs > SnodeAPI.currentOffsetTimestampMs()) .order(SnodeReceivedMessageInfo.Columns.id.desc) .fetchOne(db) diff --git a/SessionSnodeKit/SnodeAPI.swift b/SessionSnodeKit/SnodeAPI.swift index db0d2903a..4f0aff7f0 100644 --- a/SessionSnodeKit/SnodeAPI.swift +++ b/SessionSnodeKit/SnodeAPI.swift @@ -23,6 +23,14 @@ public final class SnodeAPI { /// /// - Note: Should only be accessed from `Threading.workQueue` to avoid race conditions. public static var clockOffset: Atomic = Atomic(0) + + public static func currentOffsetTimestampMs() -> Int64 { + return ( + Int64(floor(Date().timeIntervalSince1970 * 1000)) + + SnodeAPI.clockOffset.wrappedValue + ) + } + /// - Note: Should only be accessed from `Threading.workQueue` to avoid race conditions. public static var swarmCache: Atomic<[String: Set]> = Atomic([:]) @@ -546,7 +554,7 @@ public final class SnodeAPI { let lastHash = SnodeReceivedMessageInfo.fetchLastNotExpired(for: snode, namespace: namespace, associatedWith: publicKey)?.hash ?? "" // Construct signature - let timestamp = UInt64(Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.clockOffset.wrappedValue) + let timestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString() let namespaceVerificationString = (namespace == defaultNamespace ? "" : String(namespace)) @@ -647,7 +655,7 @@ public final class SnodeAPI { } // Construct signature - let timestamp = UInt64(Int64(floor(Date().timeIntervalSince1970 * 1000)) + SnodeAPI.clockOffset.wrappedValue) + let timestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString() guard From a3da087352f3b13dc873cfe4917b5d5181d7d600 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 21 Dec 2022 17:46:18 +1100 Subject: [PATCH 6/7] Fixed a few build errors and cases where the offset wasn't taken into account --- .../Conversations/Settings/OWSMessageTimerView.m | 3 ++- SessionMessagingKit/Calls/WebRTCSession.swift | 2 +- .../Jobs/Types/DisappearingMessagesJob.swift | 6 +++++- .../Sending & Receiving/MessageReceiver.swift | 2 +- .../Sending & Receiving/MessageSender.swift | 6 +++--- SessionSnodeKit/OnionRequestAPI.swift | 2 +- SessionSnodeKit/SnodeAPI.swift | 16 +++++++++++----- 7 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Session/Conversations/Settings/OWSMessageTimerView.m b/Session/Conversations/Settings/OWSMessageTimerView.m index dc71b3b06..bfe57d7e3 100644 --- a/Session/Conversations/Settings/OWSMessageTimerView.m +++ b/Session/Conversations/Settings/OWSMessageTimerView.m @@ -8,6 +8,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -75,7 +76,7 @@ const CGFloat kDisappearingMessageIconSize = 12.f; return; } - uint64_t nowTimestamp = [NSDate ows_millisecondTimeStamp]; + uint64_t nowTimestamp = [SNSnodeAPI currentOffsetTimestampMs]; CGFloat secondsLeft = (self.expirationTimestamp > nowTimestamp ? (self.expirationTimestamp - nowTimestamp) / 1000.f : 0.f); CGFloat progress = 0.f; diff --git a/SessionMessagingKit/Calls/WebRTCSession.swift b/SessionMessagingKit/Calls/WebRTCSession.swift index eced676a7..e9c789158 100644 --- a/SessionMessagingKit/Calls/WebRTCSession.swift +++ b/SessionMessagingKit/Calls/WebRTCSession.swift @@ -180,7 +180,7 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate { uuid: uuid, kind: .offer, sdps: [ sdp.sdp ], - sentTimestampMs: SnodeAPI.currentTimestampMs() + sentTimestampMs: UInt64(SnodeAPI.currentOffsetTimestampMs()) ), interactionId: nil, in: thread diff --git a/SessionMessagingKit/Jobs/Types/DisappearingMessagesJob.swift b/SessionMessagingKit/Jobs/Types/DisappearingMessagesJob.swift index 8fdd407ff..d294c27b3 100644 --- a/SessionMessagingKit/Jobs/Types/DisappearingMessagesJob.swift +++ b/SessionMessagingKit/Jobs/Types/DisappearingMessagesJob.swift @@ -60,10 +60,14 @@ public extension DisappearingMessagesJob { guard let nextExpirationTimestampMs: Double = nextExpirationTimestampMs else { return nil } + /// The `expiresStartedAtMs` timestamp is now based on the `SnodeAPI.currentOffsetTimestampMs()` value + /// so we need to make sure offset the `nextRunTimestamp` accordingly to ensure it runs at the correct local time + let clockOffsetMs: Int64 = SnodeAPI.clockOffsetMs.wrappedValue + return try? Job .filter(Job.Columns.variant == Job.Variant.disappearingMessages) .fetchOne(db)? - .with(nextRunTimestamp: ceil(nextExpirationTimestampMs / 1000)) + .with(nextRunTimestamp: ceil((nextExpirationTimestampMs - Double(clockOffsetMs)) / 1000)) .saved(db) } diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 88b9d4ea2..0c9196ac3 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -145,7 +145,7 @@ public enum MessageReceiver { message.sender = sender message.recipient = userPublicKey message.sentTimestamp = envelope.timestamp - message.receivedTimestamp = SnodeAPI.currentTimestampMs() + message.receivedTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) message.groupPublicKey = groupPublicKey message.openGroupServerMessageId = openGroupMessageServerId.map { UInt64($0) } diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 297e70732..ead951cbb 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -202,7 +202,7 @@ public final class MessageSender { recipient: message.recipient!, data: base64EncodedData, ttl: message.ttl, - timestampMs: UInt64(messageSendTimestamp + SnodeAPI.clockOffset.wrappedValue) + timestampMs: UInt64(messageSendTimestamp) ) SnodeAPI @@ -322,7 +322,7 @@ public final class MessageSender { // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set - message.sentTimestamp = SnodeAPI.currentTimestampMs() + message.sentTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) } switch destination { @@ -472,7 +472,7 @@ public final class MessageSender { // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set - message.sentTimestamp = SnodeAPI.currentTimestampMs() + message.sentTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) } message.sender = userPublicKey diff --git a/SessionSnodeKit/OnionRequestAPI.swift b/SessionSnodeKit/OnionRequestAPI.swift index d2a71b66c..65a3506ea 100644 --- a/SessionSnodeKit/OnionRequestAPI.swift +++ b/SessionSnodeKit/OnionRequestAPI.swift @@ -672,7 +672,7 @@ public enum OnionRequestAPI: OnionRequestAPIType { if let timestamp = body["t"] as? Int64 { let offset = timestamp - Int64(floor(Date().timeIntervalSince1970 * 1000)) - SnodeAPI.clockOffset.mutate { $0 = offset } + SnodeAPI.clockOffsetMs.mutate { $0 = offset } } guard 200...299 ~= statusCode else { diff --git a/SessionSnodeKit/SnodeAPI.swift b/SessionSnodeKit/SnodeAPI.swift index 4f0aff7f0..eff7c6632 100644 --- a/SessionSnodeKit/SnodeAPI.swift +++ b/SessionSnodeKit/SnodeAPI.swift @@ -19,15 +19,13 @@ public final class SnodeAPI { internal static var snodePool: Atomic> = Atomic([]) /// The offset between the user's clock and the Service Node's clock. Used in cases where the - /// user's clock is incorrect. - /// - /// - Note: Should only be accessed from `Threading.workQueue` to avoid race conditions. - public static var clockOffset: Atomic = Atomic(0) + /// user's clock is incorrect + public static var clockOffsetMs: Atomic = Atomic(0) public static func currentOffsetTimestampMs() -> Int64 { return ( Int64(floor(Date().timeIntervalSince1970 * 1000)) + - SnodeAPI.clockOffset.wrappedValue + SnodeAPI.clockOffsetMs.wrappedValue ) } @@ -1110,3 +1108,11 @@ public final class SnodeAPI { return nil } } + +@objc(SNSnodeAPI) +public final class SNSnodeAPI: NSObject { + @objc(currentOffsetTimestampMs) + public static func currentOffsetTimestampMs() -> UInt64 { + return UInt64(SnodeAPI.currentOffsetTimestampMs()) + } +} From ddc65ba73d9763f68f7dcc7dd702763e5d39e28b Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 21 Dec 2022 18:02:57 +1100 Subject: [PATCH 7/7] Set the max size for recording videos --- Session/Media Viewing & Editing/PhotoCapture.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Session/Media Viewing & Editing/PhotoCapture.swift b/Session/Media Viewing & Editing/PhotoCapture.swift index 41ec6bb30..50720f6f6 100644 --- a/Session/Media Viewing & Editing/PhotoCapture.swift +++ b/Session/Media Viewing & Editing/PhotoCapture.swift @@ -6,6 +6,7 @@ import Foundation import AVFoundation import PromiseKit import CoreServices +import SessionMessagingKit protocol PhotoCaptureDelegate: AnyObject { func photoCapture(_ photoCapture: PhotoCapture, didFinishProcessingAttachment attachment: SignalAttachment) @@ -463,6 +464,9 @@ class CaptureOutput { // leaving it enabled causes all audio to be lost on videos longer // than the default length (10s). movieOutput.movieFragmentInterval = CMTime.invalid + + // Ensure the recorded movie can't go over the maximum file server size + movieOutput.maxRecordedFileSize = Int64(FileServerAPI.maxFileSize) } var photoOutput: AVCaptureOutput? {