Added in a migration to create the user profile config and trigger a sync

# Conflicts:
#	Session.xcodeproj/project.pbxproj
pull/856/head
Morgan Pretty 2 years ago
parent d03d2ce8ab
commit f721178b49

@ -785,6 +785,7 @@
FD8ECF852934508B00C0D1BB /* BatchResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF842934508B00C0D1BB /* BatchResponseSpec.swift */; }; FD8ECF852934508B00C0D1BB /* BatchResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF842934508B00C0D1BB /* BatchResponseSpec.swift */; };
FD8ECF8629346DA100C0D1BB /* HeaderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906127E411AF00CD579F /* HeaderSpec.swift */; }; FD8ECF8629346DA100C0D1BB /* HeaderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906127E411AF00CD579F /* HeaderSpec.swift */; };
FD8ECF8729346DB500C0D1BB /* RequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906327E4122F00CD579F /* RequestSpec.swift */; }; FD8ECF8729346DB500C0D1BB /* RequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3C906327E4122F00CD579F /* RequestSpec.swift */; };
FD8ECF892935AB7200C0D1BB /* SessionUtilError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */; };
FD90040F2818AB6D00ABAAF6 /* GetSnodePoolJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */; }; FD90040F2818AB6D00ABAAF6 /* GetSnodePoolJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */; };
FD9004122818ABDC00ABAAF6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73F280402C4004C14C5 /* Job.swift */; }; FD9004122818ABDC00ABAAF6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73F280402C4004C14C5 /* Job.swift */; };
FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */; }; FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */; };
@ -1905,6 +1906,7 @@
FD8ECF7E2934298100C0D1BB /* SharedConfigDump.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedConfigDump.swift; sourceTree = "<group>"; }; FD8ECF7E2934298100C0D1BB /* SharedConfigDump.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedConfigDump.swift; sourceTree = "<group>"; };
FD8ECF812934387A00C0D1BB /* ConfigUserProfileSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigUserProfileSpec.swift; sourceTree = "<group>"; }; FD8ECF812934387A00C0D1BB /* ConfigUserProfileSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigUserProfileSpec.swift; sourceTree = "<group>"; };
FD8ECF842934508B00C0D1BB /* BatchResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchResponseSpec.swift; sourceTree = "<group>"; }; FD8ECF842934508B00C0D1BB /* BatchResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchResponseSpec.swift; sourceTree = "<group>"; };
FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionUtilError.swift; sourceTree = "<group>"; };
FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetSnodePoolJob.swift; sourceTree = "<group>"; }; FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetSnodePoolJob.swift; sourceTree = "<group>"; };
FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; }; FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; };
FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessageSendsJob.swift; sourceTree = "<group>"; }; FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessageSendsJob.swift; sourceTree = "<group>"; };
@ -4027,6 +4029,7 @@
children = ( children = (
FD8ECF7829340F7100C0D1BB /* libsession-util.xcframework */, FD8ECF7829340F7100C0D1BB /* libsession-util.xcframework */,
FD8ECF7A29340FFD00C0D1BB /* SessionUtil.swift */, FD8ECF7A29340FFD00C0D1BB /* SessionUtil.swift */,
FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */,
); );
path = LibSessionUtil; path = LibSessionUtil;
sourceTree = "<group>"; sourceTree = "<group>";
@ -5564,6 +5567,8 @@
FD245C59285065FC00B966DD /* ControlMessage.swift in Sources */, FD245C59285065FC00B966DD /* ControlMessage.swift in Sources */,
B8DE1FB626C22FCB0079C9CE /* CallMessage.swift in Sources */, B8DE1FB626C22FCB0079C9CE /* CallMessage.swift in Sources */,
FD245C50285065C700B966DD /* VisibleMessage+Quote.swift in Sources */, FD245C50285065C700B966DD /* VisibleMessage+Quote.swift in Sources */,
FD8ECF892935AB7200C0D1BB /* SessionUtilError.swift in Sources */,
FD8ECF42292B340D00C0D1BB /* SOGSBatchRequest.swift in Sources */,
FD5C7307284F103B0029977D /* MessageReceiver+MessageRequests.swift in Sources */, FD5C7307284F103B0029977D /* MessageReceiver+MessageRequests.swift in Sources */,
C3A71D0B2558989C0043A11F /* MessageWrapper.swift in Sources */, C3A71D0B2558989C0043A11F /* MessageWrapper.swift in Sources */,
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */, FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */,

@ -27,7 +27,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// MARK: - Lifecycle // MARK: - Lifecycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
SessionUtil.loadState() // TODO: Remove this (move to 'Configuration'? Or call directly as part of 'AppSetup'?)
// These should be the first things we do (the startup process can fail without them) // These should be the first things we do (the startup process can fail without them)
SetCurrentAppContext(MainAppContext()) SetCurrentAppContext(MainAppContext())
verifyDBKeysAvailableBeforeBackgroundLaunch() verifyDBKeysAvailableBeforeBackgroundLaunch()

@ -13,7 +13,7 @@ internal struct ConfigDump: Codable, Equatable, Hashable, Identifiable, Fetchabl
case data case data
} }
enum Variant: String, Codable, DatabaseValueConvertible { enum Variant: String, Codable, DatabaseValueConvertible, CaseIterable {
case userProfile case userProfile
} }

@ -5,74 +5,140 @@ import GRDB
import SessionUtil import SessionUtil
import SessionUtilitiesKit import SessionUtilitiesKit
/*internal*/public enum SessionUtil { // TODO: Rename this to be cleaner? /*internal*/public enum SessionUtil {
typealias ConfResult = (needsPush: Bool, needsDump: Bool)
// MARK: - Configs
private static var userProfileConfig: Atomic<UnsafeMutablePointer<config_object>?> = Atomic(nil)
// MARK: - Variables
public static var needsSync: Bool {
return ConfigDump.Variant.allCases.contains { variant in
switch variant {
case .userProfile:
return (userProfileConfig.wrappedValue.map { config_needs_push($0) } ?? false)
}
}
}
// MARK: - Loading
/*internal*/public static func loadState() { /*internal*/public static func loadState() {
SessionUtil.userProfileConfig.mutate { $0 = loadState(for: .userProfile) }
}
private static func loadState(for variant: ConfigDump.Variant) -> UnsafeMutablePointer<config_object>? {
// Load any
let storedDump: Data? = Storage.shared let storedDump: Data? = Storage.shared
.read { db in try ConfigDump.fetchOne(db, id: .userProfile) }? .read { db in try ConfigDump.fetchOne(db, id: variant) }?
.data .data
var dump: UnsafePointer<CChar>? = nil // TODO: Load from DB/Disk
let dumpLen: size_t = 0
var conf: UnsafeMutablePointer<config_object>? = nil
// var confSetup: UnsafeMutablePointer<UnsafeMutablePointer<config_object>?>? = nil
var error: UnsafeMutablePointer<CChar>? = nil
// TODO: Will need to manually release any unsafe pointers
let result = user_profile_init(&conf, dump, dumpLen, error)
guard result == 0 else { return } // TODO: Throw error return try? loadState(for: variant, cachedData: storedDump)
}
// var conf: UnsafeMutablePointer<config_object>? = confSetup?.pointee
user_profile_set_name(conf, "TestName") // TODO: Confirm success
let profileUrl: [CChar] = "http://example.org/omg-pic-123.bmp".bytes.map { CChar(bitPattern: $0) } internal static func loadState(
let profileKey: [CChar] = "secretNOTSECRET".bytes.map { CChar(bitPattern: $0) } for variant: ConfigDump.Variant,
let profilePic: user_profile_pic = profileUrl.withUnsafeBufferPointer { profileUrlPtr in cachedData: Data? = nil
profileKey.withUnsafeBufferPointer { profileKeyPtr in ) throws -> UnsafeMutablePointer<config_object>? {
user_profile_pic( // Setup initial variables (including getting the memory address for any cached data)
url: profileUrlPtr.baseAddress, var conf: UnsafeMutablePointer<config_object>? = nil
key: profileKeyPtr.baseAddress, let error: UnsafeMutablePointer<CChar>? = nil
keylen: profileKey.count let cachedDump: (data: UnsafePointer<CChar>, length: Int)? = cachedData?.withUnsafeBytes { unsafeBytes in
return unsafeBytes.baseAddress.map {
(
$0.assumingMemoryBound(to: CChar.self),
unsafeBytes.count
) )
} }
} }
user_profile_set_pic(conf, profilePic) // TODO: Confirm success // No need to deallocate the `cachedDump.data` as it'll automatically be cleaned up by
// the `cachedData` lifecycle, but need to deallocate the `error` if it gets set
if config_needs_push(conf) { defer {
print("Needs Push!!!") error?.deallocate()
} }
if config_needs_dump(conf) { // Try to create the object
print("Needs Dump!!!") let result: Int32 = {
switch variant {
case .userProfile:
return user_profile_init(&conf, cachedDump?.data, (cachedDump?.length ?? 0), error)
}
}()
guard result == 0 else {
let errorString: String = (error.map { String(cString: $0) } ?? "unknown error")
SNLog("[SessionUtil Error] Unable to create \(variant.rawValue) config object: \(errorString)")
throw SessionUtilError.unableToCreateConfigObject
} }
var toPush: UnsafeMutablePointer<CChar>? = nil return conf
var pushLen: Int = 0 }
let seqNo = config_push(conf, &toPush, &pushLen)
//var remoteAddr: [CChar] = remote.bytes.map { CChar(bitPattern: $0) } internal static func saveState(
//config_dump(conf, &dump1, &dump1len); _ db: Database,
conf: UnsafeMutablePointer<config_object>?,
for variant: ConfigDump.Variant
) throws {
guard conf != nil else { throw SessionUtilError.nilConfigObject }
free(toPush) // TODO: Confirm // If it doesn't need a dump then do nothing
guard config_needs_dump(conf) else { return }
var dumpResult: UnsafeMutablePointer<CChar>? = nil var dumpResult: UnsafeMutablePointer<CChar>? = nil
var dumpResultLen: Int = 0 var dumpResultLen: Int = 0
config_dump(conf, &dumpResult, &dumpResultLen) config_dump(conf, &dumpResult, &dumpResultLen)
print("RAWR") guard let dumpResult: UnsafeMutablePointer<CChar> = dumpResult else { return }
let str = String(cString: dumpResult!)
let stryBytes = str.bytes let dumpData: Data = Data(bytes: dumpResult, count: dumpResultLen)
let hexStr = stryBytes.toHexString() dumpResult.deallocate()
let data = Data(bytes: dumpResult!, count: dumpResultLen)
// dumpResult. try ConfigDump(
// Storage.shared.write { db in variant: variant,
// try ConfigDump(variant: .userProfile, data: <#T##Data#>) data: dumpData
// .save(db) )
// } .save(db)
// }
print("RAWR2")
// MARK: - UserProfile
//String(cString: dumpResult!)
internal static func update(
conf: UnsafeMutablePointer<config_object>?,
with profile: Profile
) throws -> ConfResult {
guard conf != nil else { throw SessionUtilError.nilConfigObject }
// Update the name
user_profile_set_name(conf, profile.name)
let profilePic: user_profile_pic? = profile.profilePictureUrl?
.bytes
.map { CChar(bitPattern: $0) }
.withUnsafeBufferPointer { profileUrlPtr in
let profileKey: [CChar]? = profile.profileEncryptionKey?
.keyData
.bytes
.map { CChar(bitPattern: $0) }
return profileKey?.withUnsafeBufferPointer { profileKeyPtr in
user_profile_pic(
url: profileUrlPtr.baseAddress,
key: profileKeyPtr.baseAddress,
keylen: (profileKey?.count ?? 0)
)
}
}
if let profilePic: user_profile_pic = profilePic {
user_profile_set_pic(conf, profilePic)
}
return (
needsPush: config_needs_push(conf),
needsDump: config_needs_dump(conf)
)
} }
} }

@ -0,0 +1,8 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
public enum SessionUtilError: Error {
case unableToCreateConfigObject
case nilConfigObject
}

@ -8,6 +8,17 @@ extension Collection {
} }
} }
public extension Collection {
/// This creates an UnsafeMutableBufferPointer to access data in memory directly. This result pointer provides no automated
/// memory management so after use you are responsible for handling the life cycle and need to call `deallocate()`.
func unsafeCopy() -> UnsafeMutableBufferPointer<Element> {
let copy = UnsafeMutableBufferPointer<Element>.allocate(capacity: self.underestimatedCount)
_ = copy.initialize(from: self)
return copy
}
}
public extension Collection where Element == [CChar] { public extension Collection where Element == [CChar] {
/// This creates an array of UnsafePointer types to access data of the C strings in memory. This array provides no automated /// This creates an array of UnsafePointer types to access data of the C strings in memory. This array provides no automated
/// memory management of it's children so after use you are responsible for handling the life cycle of the child elements and /// memory management of it's children so after use you are responsible for handling the life cycle of the child elements and

@ -74,8 +74,13 @@ public enum AppSetup {
], ],
onProgressUpdate: migrationProgressChanged, onProgressUpdate: migrationProgressChanged,
onComplete: { result, needsConfigSync in onComplete: { result, needsConfigSync in
// After the migrations have run but before the migration completion we load the
// SessionUtil state and update the 'needsConfigSync' flag based on whether the
// configs also need to be sync'ed
SessionUtil.loadState()
DispatchQueue.main.async { DispatchQueue.main.async {
migrationsCompletion(result, needsConfigSync) migrationsCompletion(result, (needsConfigSync || SessionUtil.needsSync))
// The 'if' is only there to prevent the "variable never read" warning from showing // The 'if' is only there to prevent the "variable never read" warning from showing
if backgroundTask != nil { backgroundTask = nil } if backgroundTask != nil { backgroundTask = nil }

Loading…
Cancel
Save