From 9245409b12765bdbf708ed86633914734ec20813 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Sun, 10 Sep 2023 12:33:59 -0400 Subject: [PATCH] fix(ios): correct ios version fix(ios): Correct iOS version, fix checkConnection and init issues --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + example/ios/Podfile | 2 +- example/ios/Podfile.lock | 8 +- ios/Cryptography.swift | 15 +- ios/Fula.mm | 2 +- ios/Fula.swift | 275 +++++++++++------- package.json | 2 +- 7 files changed, 201 insertions(+), 111 deletions(-) create mode 100644 example/ios/FulaExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/FulaExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/FulaExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/FulaExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Podfile b/example/ios/Podfile index c476ece..92addb0 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -5,7 +5,7 @@ require Pod::Executable.execute_command('node', ['-p', {paths: [process.argv[1]]}, )', __dir__]).strip -platform :ios, '13.0' +platform :ios, '14.0' prepare_react_native_project! # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 7e356ed..64ad9b1 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -377,7 +377,7 @@ PODS: - React-jsinspector (0.72.3) - React-logger (0.72.3): - glog - - react-native-fula (1.14.2): + - react-native-fula (1.14.6): - CryptoSwift (~> 1.7.1) - Fula (~> 1.0.0) - RCT-Folly (= 2021.07.22.00) @@ -712,7 +712,7 @@ SPEC CHECKSUMS: React-jsiexecutor: 59d1eb03af7d30b7d66589c410f13151271e8006 React-jsinspector: b511447170f561157547bc0bef3f169663860be7 React-logger: c5b527272d5f22eaa09bb3c3a690fee8f237ae95 - react-native-fula: f7df65e1d0931640568e9e19eb048ce40fd348f9 + react-native-fula: 17a71317faa0b12fdb5d77c4d4560972be871ec7 React-NativeModulesApple: c57f3efe0df288a6532b726ad2d0322a9bf38472 React-perflogger: 6bd153e776e6beed54c56b0847e1220a3ff92ba5 React-RCTActionSheet: c0b62af44e610e69d9a2049a682f5dba4e9dff17 @@ -737,6 +737,6 @@ SPEC CHECKSUMS: Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 18e6e42feb52b2840969de671a351f681edeffed +PODFILE CHECKSUM: 894d220cf9833d2e19f55138952974df1c3d2b30 -COCOAPODS: 1.12.0 +COCOAPODS: 1.12.1 diff --git a/ios/Cryptography.swift b/ios/Cryptography.swift index a154866..527f572 100644 --- a/ios/Cryptography.swift +++ b/ios/Cryptography.swift @@ -1,13 +1,26 @@ import Foundation import CommonCrypto import CryptoSwift +import os.log + + public class Cryptography: NSObject { public static func encryptMsg(_ message: Array, _ secretKey: Array) throws -> String { + OSLog.viewCycle.info("ReactNative encryptMsg started for \(message)") let aes = try! AES(key: secretKey, blockMode: ECB(), padding: .pkcs5) + OSLog.viewCycle.info("ReactNative encryptMsg aes") let encrypted = try! aes.encrypt(message) - return Data(encrypted).base64EncodedString() + OSLog.viewCycle.info("ReactNative encryptMsg encrypted") + do{ + let data = Data(encrypted).base64EncodedString() + OSLog.viewCycle.info("ReactNative encryptMsg: \(data)") + return data + } catch let error { + OSLog.viewCycle.info("ReactNative encryptMsg error: \(error.localizedDescription)") + throw error + } } public static func decryptMsg(_ cipherText: String, _ secretKey: Array) diff --git a/ios/Fula.mm b/ios/Fula.mm index 05689e2..f0cf77e 100644 --- a/ios/Fula.mm +++ b/ios/Fula.mm @@ -2,7 +2,7 @@ @interface RCT_EXTERN_MODULE(FulaModule, NSObject) -RCT_EXTERN_METHOD(checkConnection: (NSNumber *) timeout +RCT_EXTERN_METHOD(checkConnection: (nonnull NSNumber *) timeout withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) diff --git a/ios/Fula.swift b/ios/Fula.swift index 0103e60..a82d848 100644 --- a/ios/Fula.swift +++ b/ios/Fula.swift @@ -3,6 +3,32 @@ import Foundation.NSDate // for TimeInterval import CommonCrypto import Wnfs import Fula +import os.log + +extension OSLog { + + private static var subsystem = Bundle.main.bundleIdentifier! + + /// Logs the view cycles like a view that appeared. + static let viewCycle = OSLog(subsystem: subsystem, category: "viewcycle") + + /// All logs related to tracking and analytics. + static let statistics = OSLog(subsystem: subsystem, category: "statistics") +} + +extension OSLog { + + func info(_ msg: String, _ args: CVarArg...) { + os_log("%{public}@", log: self, type: .info, msg) + } + + func error(_ msg: String, _ args: CVarArg...) { + os_log("%{public}@", log: self, type: .error, msg) + } + + // ... (more methods for different log levels, if needed) +} + @objc(FulaModule) class FulaModule: NSObject { @@ -110,28 +136,33 @@ class FulaModule: NSObject { } @objc(checkConnection:withResolver:withRejecter:) - func checkConnection(timeout: Int, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) { - print("ReactNative", "checkConnection started") - if (fula != nil) { - do { - // FIXME: run with timeout - // Task { - // try await withTimeout(seconds: TimeInterval(timeout)) { [weak self] in - // guard let weakSelf = self else { return false } - // try weakSelf.checkConnectionInternal() - // callback(BOOL(true)) - // } - // } - resolve(try self.checkConnectionInternal()) - } - catch let error { - print("ReactNative", "checkConnection failed with Error: ", error.localizedDescription) - // callback(BOOL(false)) - resolve(false) + func checkConnection(timeout: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + OSLog.viewCycle.info("ReactNative checkConnection started with timeout=\(timeout)") + + if let timeoutInt = timeout as? Int { + if fula != nil { + DispatchQueue.global(qos: .default).async { + do { + let connectionStatus = try self.checkConnectionInternal(timeout: timeoutInt) + OSLog.viewCycle.info("ReactNative checkConnection ended \(connectionStatus)") + resolve(connectionStatus) + } + catch let error { + OSLog.viewCycle.info("ReactNative checkConnection failed with Error: \(error.localizedDescription)") + resolve(false) + } } + } else { + OSLog.viewCycle.info("ReactNative checkConnection fula is null") + resolve(false) } + } else { + OSLog.viewCycle.error("ReactNative checkConnection - invalid timeout value") + reject("ERR_INVALID_TIMEOUT", "Invalid timeout value", nil) + } } + @objc(newClient:withStorePath:withBloxAddr:withExchange:withAutoFlush:withUseRelay:withRefresh:withResolver:withRejecter:) func newClient(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { print("ReactNative", "newClient storePath= " , storePath , " bloxAddr= " , bloxAddr , " exchange= " , exchange , " autoFlush= " , autoFlush , " useRelay= " , useRelay , " refresh= " , refresh); @@ -174,22 +205,24 @@ class FulaModule: NSObject { // function to be compatible with the android version. @objc(initFula:withStorePath:withBloxAddr:withExchange:withAutoFlush:withRootConfig:withUseRelay:withRefresh:withResolver:withRejecter:) func initFula(identityString: String, storePath: String, bloxAddr: String, exchange: String, autoFlush: Bool, rootConfig: String, useRelay: Bool, refresh: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { - print("ReactNative", "init started") + + OSLog.viewCycle.info("ReactNative - init started") + do { var resultData = Dictionary() - print("ReactNative", "init storePath= ", storePath) + OSLog.viewCycle.info("ReactNative init storePath= \(storePath)") let identity = self.toByte(identityString) - print("ReactNative", "init identity= ", identityString) + OSLog.viewCycle.info("ReactNative init identity= \(identityString)") let obj = try initInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, _rootCid: rootConfig, useRelay: useRelay, refresh: refresh) - print("ReactNative", "init object created: [ " + obj[0] + ", " + obj[1] + ", " + obj[2] + " ]") + OSLog.viewCycle.info("ReactNative init object created: [ \(obj[0]), \(obj[1]), \(obj[2]) ]") resultData["peerId"] = obj[0] resultData["rootCid"] = obj[1] resultData["wnfs_key"] = obj[2] resolve(resultData as NSDictionary) } catch let error { - print("ReactNative", "init failed with Error: ", error.localizedDescription) + OSLog.viewCycle.info("ReactNative init failed with Error: \(error.localizedDescription)") reject("ERR_FULA", "init failed", error) } @@ -212,85 +245,108 @@ class FulaModule: NSObject { } - func checkConnectionInternal() throws { - print("ReactNative", "checkConnectionInternal started") - if (fula != nil) { - do { - print("ReactNative", "connectToBlox started") - try fula?.connectToBlox() - } catch let error { - print("ReactNative", "checkConnectionInternal failed with Error: ", error.localizedDescription) - throw error + func checkConnectionInternal(timeout: Int) throws -> Bool { + OSLog.viewCycle.info("ReactNative checkConnectionInternal started with timeout: \(timeout)") + var connectionStatus = false + + if let fula = self.fula { + let semaphore = DispatchSemaphore(value: 0) + let queue = DispatchQueue(label: "com.yourapp.checkConnection", attributes: .concurrent) + + queue.async { + do { + OSLog.viewCycle.info("ReactNative connectToBlox started") + try fula.connectToBlox() + connectionStatus = true + OSLog.viewCycle.info("ReactNative checkConnectionInternal succeeded") + semaphore.signal() + } catch let error { + OSLog.viewCycle.info("ReactNative checkConnectionInternal failed with Error: \(error.localizedDescription)") + semaphore.signal() + } + } + + let timeoutResult = semaphore.wait(timeout: .now() + .seconds(timeout)) + switch timeoutResult { + case .timedOut: + OSLog.viewCycle.info("ReactNative checkConnectionInternal timed out") + return false + case .success: + return connectionStatus } } else { - print("ReactNative", "checkConnectionInternal failed because fula is not initialized ") + OSLog.viewCycle.info("ReactNative checkConnectionInternal failed because fula is not initialized") + return false } } - @objc(checkFailedActions:withResolver:withRejecter:) - func checkFailedActions(retry: Bool, resolve:RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) -> Void{ - do { - if (fula != nil) { - if (!retry) { - print("ReactNative", "checkFailedActions without retry") - let failedLinks = try fula!.listFailedPushes() - if (failedLinks.hasNext()) { - print("ReactNative", "checkFailedActions found: ", try failedLinks.next().toHex()) + @objc(checkFailedActions:withTimeout:withResolver:withRejecter:) + func checkFailedActions(retry: Bool, timeout: Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void { + do { + guard let fula = fula else { + throw NSError(domain: "ERR_FULA", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Fula is not initialized"]) + } + + if !retry { + OSLog.viewCycle.info("ReactNative checkFailedActions without retry") + let failedLinks = try fula.listFailedPushes() + + let nextFailedLink = try failedLinks.next() + if nextFailedLink != nil { + // Assuming nextFailedLink is of type Data; replace `toHex()` with an appropriate method to convert Data to a hex string + OSLog.viewCycle.info("ReactNative checkFailedActions found") resolve(true) } else { resolve(false) } } else { - print("ReactNative", "checkFailedActions with retry") - - let retryResults = try retryFailedActionsInternal() - resolve(!retryResults) - + OSLog.viewCycle.info("ReactNative checkFailedActions with retry") + let retryResults = try retryFailedActionsInternal(timeout: timeout) // Ensure retryFailedActionsInternal accepts a timeout parameter + resolve(!retryResults) } - } else { - reject("ERR_FULA", "Fula is not initialized", nil) + } catch let error { + OSLog.viewCycle.info("ReactNative checkFailedActions failed with Error: \(error.localizedDescription)") + reject("ERR_FULA", "CheckFailedActions failed", error) } - } catch let error { - print("ReactNative", "checkFailedActions failed with Error: ", error.localizedDescription) - reject("ERR_FULA", "CheckFailedActions failed", error) - } } - func retryFailedActionsInternal() throws -> Bool { - print("ReactNative", "retryFailedActionsInternal started") - if (fula != nil) { - //Fula is initialized - do { - try checkConnectionInternal() + + func retryFailedActionsInternal(timeout: Int) throws -> Bool { + OSLog.viewCycle.info("ReactNative retryFailedActionsInternal started") + + guard let fula = fula else { + OSLog.viewCycle.info("ReactNative retryFailedActionsInternal failed because fula is not initialized") + return false + } + + do { + let connectionCheck = try checkConnectionInternal(timeout: timeout) + + if connectionCheck { do { - print("ReactNative", "retryFailedPushes started") - try fula?.retryFailedPushes() - print("ReactNative", "flush started") - try fula?.flush() + OSLog.viewCycle.info("ReactNative retryFailedPushes started") + try fula.retryFailedPushes() + OSLog.viewCycle.info("ReactNative flush started") + try fula.flush() return true - } - catch let error { - try fula?.flush() - print("ReactNative", "retryFailedActionsInternal failed with Error: ", error.localizedDescription) + } catch let error { + try fula.flush() + OSLog.viewCycle.info("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)") return false } - - - } - catch let error { - print("ReactNative", "retryFailedActions failed with Error: ", error.localizedDescription) + } else { + OSLog.viewCycle.info("ReactNative retryFailedActionsInternal failed because blox is offline") return false } - } else { - print("ReactNative", "retryFailedActions failed because fula is not initialized") - //Fula is not initialized + } catch let error { + OSLog.viewCycle.info("ReactNative retryFailedActionsInternal failed with Error: \(error.localizedDescription)") return false } - } + func createPeerIdentity(privateKey: Data) throws -> Data { do { // 1: First: create public key from provided private key @@ -331,31 +387,44 @@ class FulaModule: NSObject { try encryptAndStoreConfig() } - func loadWnfs(_ wnfsKey: Data , _ _rootCid: String) throws { - print("ReactNative", "loadWnfs called: rootCid=", _rootCid) - let hash32 = wnfsKey.sha256() - print("ReactNative", "wnfsKey=" , wnfsKey.toHex() , "; hash32 = " , hash32.toHex()); + func loadWnfs(_ _wnfsKey: Data , _ _rootCid: String) throws { + OSLog.viewCycle.info("ReactNative loadWnfs called: rootCid=\(_rootCid)") + let hash32 = _wnfsKey.sha256() + OSLog.viewCycle.info("ReactNative wnfsKey= \(_wnfsKey.toHex()) ; hash32 = \(hash32.toHex())"); try wnfs?.LoadWithWNFSKey(wnfsKey: hash32, cid: _rootCid) rootCid = _rootCid + wnfsKey = _wnfsKey if (fula != nil) { try fula?.flush() } - print("ReactNative", "loadWnfs completed") + OSLog.viewCycle.info("ReactNative loadWnfs completed") try encryptAndStoreConfig() } func encryptAndStoreConfig() throws { do { - if(identityEncryptedGlobal != nil) { - let cid_encrypted = try Cryptography.encryptMsg(rootCid!.toUint8Array(), secretKeyGlobal!) - let wnfs_key_encrypted = try Cryptography.encryptMsg(wnfsKey!.toUint8Array(), secretKeyGlobal!) - - userDataHelper.add("cid_encrypted_" + identityEncryptedGlobal!, cid_encrypted) - userDataHelper.add("wnfs_key_encrypted_" + identityEncryptedGlobal!, wnfs_key_encrypted) + if let identityEncryptedGlobalUnwrapped = identityEncryptedGlobal { + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig started") + + if let rootCidUnwrapped = rootCid, let wnfsKeyUnwrapped = wnfsKey, let secretKeyGlobalUnwrapped = secretKeyGlobal { + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig started with rootCid: \(rootCidUnwrapped.toUint8Array()) and wnfsKey:\(wnfsKeyUnwrapped)") + + let cid_encrypted = try Cryptography.encryptMsg(rootCidUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped) + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig cid_encrypted: \(cid_encrypted)") + + let wnfs_key_encrypted = try Cryptography.encryptMsg(wnfsKeyUnwrapped.toUint8Array(), secretKeyGlobalUnwrapped) + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig wnfs_key_encrypted: \(wnfs_key_encrypted)") + + userDataHelper.add("cid_encrypted_" + identityEncryptedGlobalUnwrapped, cid_encrypted) + userDataHelper.add("wnfs_key_encrypted_" + identityEncryptedGlobalUnwrapped, wnfs_key_encrypted) + } else { + // Handle the case where rootCid, wnfsKey, or secretKeyGlobal is nil + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig failed because one of the values is nil") + } } } catch let error { - print("ReactNative", "encryptAndStoreConfig failed with Error: ", error.localizedDescription) + OSLog.viewCycle.info("ReactNative encryptAndStoreConfig failed with Error: \(error.localizedDescription)") throw error } } @@ -443,7 +512,7 @@ class FulaModule: NSObject { do { if (fula == nil || refresh) { try newClientInternal(identity: identity, storePath: storePath, bloxAddr: bloxAddr, exchange: exchange, autoFlush: autoFlush, useRelay: useRelay, refresh: refresh) - print("ReactNative", "fula initialized: " + fula!.id_()) + OSLog.viewCycle.info("ReactNative fula initialized: \(self.fula!.id_())") } if(client == nil || refresh) { client = Client(clientInput: fula!) @@ -458,7 +527,7 @@ class FulaModule: NSObject { } return try c.get(cid) }) - print("ReactNative", "wnfs initialized") + OSLog.viewCycle.info("ReactNative wnfs initialized") } let secretKey = try Cryptography.generateKey(identity) @@ -467,35 +536,35 @@ class FulaModule: NSObject { secretKeyGlobal = secretKey if (rootCid == nil || rootCid!.isEmpty) { - print("ReactNative", "rootCid is empty.") + OSLog.viewCycle.info("ReactNative rootCid is empty.") //Load from keystore let cid_encrypted_fetched = userDataHelper.getValue("cid_encrypted_"+identity_encrypted) - print("ReactNative", "Here1") + OSLog.viewCycle.info("ReactNative Here1") var cid: Array? = nil if(cid_encrypted_fetched != nil && !cid_encrypted_fetched!.isEmpty) { - print("ReactNative", "decrypting cid="+cid_encrypted_fetched!+" with secret="+secretKey.toHex()) + OSLog.viewCycle.info("ReactNative decrypting cid= \(cid_encrypted_fetched!) with secret \(secretKey.toHex())") cid = try Cryptography.decryptMsg(cid_encrypted_fetched!, secretKey) } print("ReactNative", "Here2") //print("ReactNative", "Attempted to fetch cid from keystore cid="+cid+" & wnfs_key="+wnfs_key) if(cid == nil || cid!.isEmpty){ - print("ReactNative", "cid or wnfs key was not found") + OSLog.viewCycle.info("ReactNative cid or wnfs key was not found") if(!_rootCid.isEmpty){ - print("ReactNative", "Re-setting cid from input: "+_rootCid) + OSLog.viewCycle.info("ReactNative Re-setting cid from input: \(_rootCid)") cid = _rootCid.toUint8Array() } } if(cid == nil || cid!.isEmpty){ - print("ReactNative", "Tried to recover cid but was not successful. Creating ones") + OSLog.viewCycle.info("ReactNative Tried to recover cid but was not successful. Creating ones") try createNewrootCid(identity: identity) } else { - print("ReactNative", "Found cid and wnfs key in keychain store") - print("ReactNative", "Recovered cid and private ref from keychain store. cid=",cid!," & wnfs_key=",identity) + OSLog.viewCycle.info("ReactNative Found cid and wnfs key in keychain store") + OSLog.viewCycle.info("ReactNative Recovered cid and private ref from keychain store. cid=\(cid!) & wnfs_key=\(identity)") try loadWnfs(identity, cid!.toData().toUTF8String()!) } - print("ReactNative", "creating/reloading rootCid completed") + OSLog.viewCycle.info("ReactNative creating/reloading rootCid completed") /* byte[] testbyte = convertStringToByte("-104,40,24,-93,24,100,24,114,24,111,24,111,24,116,24,-126,24,-126,0,0,24,-128,24,103,24,118,24,101,24,114,24,115,24,105,24,111,24,110,24,101,24,48,24,46,24,49,24,46,24,48,24,105,24,115,24,116,24,114,24,117,24,99,24,116,24,117,24,114,24,101,24,100,24,104,24,97,24,109,24,116") @@ -508,22 +577,22 @@ class FulaModule: NSObject { */ - print("ReactNative", "rootCid is created: cid=" , rootCid!,"& wnfs_key=",wnfsKey!.toHex()) + OSLog.viewCycle.info("ReactNative rootCid is created: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())") } else { - print("ReactNative", "rootCid existed: cid=" , rootCid!," & wnfs_key=",wnfsKey!.toHex()) + OSLog.viewCycle.info("ReactNative rootCid existed: cid=\(self.rootCid!) & wnfs_key=\(self.wnfsKey!.toHex())") } let peerId = fula!.id_() var obj = [String]() obj.append(peerId) obj.append(rootCid!) obj.append(wnfsKey!.toHex()) - print("ReactNative", "initInternal is completed successfully") + OSLog.viewCycle.info("ReactNative initInternal is completed successfully") if (fula != nil) { try fula?.flush() } return obj } catch let error { - print("ReactNative", "init internal failed with Error: " , error.localizedDescription) + OSLog.viewCycle.info("ReactNative init internal failed with Error: \(error.localizedDescription)") throw error } } diff --git a/package.json b/package.json index 1ca48fd..d232b15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@functionland/react-native-fula", - "version": "1.14.6", + "version": "1.14.7", "description": "This package is a bridge to use the Fula libp2p protocols in the react-native which is using wnfs", "main": "lib/commonjs/index", "module": "lib/module/index",