From b62f2acca7bd5037091c28c31741dc08ee756a13 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Thu, 2 Jun 2022 18:24:45 +0100 Subject: [PATCH] trying to send service endpoint via mach message - it does not work --- apps/ios/Shared/FPService.swift | 6 ++++ apps/ios/Shared/SimpleXApp.swift | 35 ++++++++++++++++--- .../FileProviderExtension.swift | 25 +++++++++++-- apps/ios/SimpleX.xcodeproj/project.pbxproj | 18 ++++++++++ apps/ios/SimpleXChat/AppGroup.swift | 27 +++++++++++--- 5 files changed, 99 insertions(+), 12 deletions(-) diff --git a/apps/ios/Shared/FPService.swift b/apps/ios/Shared/FPService.swift index 2409d624df..9447e5fbb4 100644 --- a/apps/ios/Shared/FPService.swift +++ b/apps/ios/Shared/FPService.swift @@ -9,6 +9,7 @@ import Foundation import FileProvider import SimpleX_Service +import SimpleXChat let SIMPLEX_SERVICE_NAME = NSFileProviderServiceName("group.chat.simplex.app.service") let SERVICE_PROXY_ITEM = "chat.simplex.service:/123" @@ -24,8 +25,13 @@ func testFPService() { let manager = NSFileProviderManager.default // TODO try access file logger.debug("testFPService NSFileProviderManager.documentStorageURL \(manager.documentStorageURL, privacy: .public)") + +// let res = machMessenger.sendMessageWithReply(FPS_MACH_PORT, msg: "machMessenger before getFileProviderServicesForItem") +// print("reply 1", res) FileManager.default.getFileProviderServicesForItem(at: URL(string: "\(manager.documentStorageURL)123")!) { (services, error) in +// let res = machMessenger.sendMessageWithReply(FPS_MACH_PORT, msg: "machMessenger after getFileProviderServicesForItem") +// print("reply 2", res) // Check to see if an error occurred. guard error == nil else { diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index 853c1e1154..4591d76b4f 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -11,11 +11,38 @@ import SimpleXChat let logger = Logger() -let machMessenger = MachMessenger(APP_MACH_PORT, callback: receivedNSEMachMessage) +let machMessenger = MachMessenger(APP_MACH_PORT, callback: receivedMachMessage) -func receivedNSEMachMessage(msgId: Int32, msg: String) -> String? { - logger.debug("MachMessenger: receivedNSEMachMessage \"\(msg)\" from NSE, replying") - return "reply from App to: \(msg)" +func receivedMachMessage(msgId: Int32, msg: String) -> String? { +// logger.debug("MachMessenger: receivedMachMessage \"\(msg)\" from NSE, replying") +// return "reply from App to: \(msg)" + + if let data = msg.data(using: .utf8) { + let endpoint = try! NSKeyedUnarchiver.unarchivedObject(ofClass: NSXPCListenerEndpoint.self, from: data)! + let connection = NSXPCConnection(listenerEndpoint: endpoint) + connection.remoteObjectInterface = NSXPCInterface(with: SimpleXFPServiceProtocol.self) + + // Start the connection. + connection.resume() + + // Get the proxy object. + let rawProxy = connection.remoteObjectProxyWithErrorHandler({ (errorAccessingRemoteObject) in + // Handle the error here... + }) + + // Cast the proxy object to the interface's protocol. + guard let proxy = rawProxy as? SimpleXFPServiceProtocol else { + // If the interface is set up properly, this should never fail. + fatalError("*** Unable to cast \(rawProxy) to a DesiredProtocol instance ***") + } + + logger.debug("testFPService calling service") + proxy.upperCaseString("hello to service", withReply: { reply in + logger.debug("testFPService reply from service \(reply)") + }) + + } + return nil } @main diff --git a/apps/ios/SimpleX Service/FileProviderExtension.swift b/apps/ios/SimpleX Service/FileProviderExtension.swift index d46b74aaa9..1321449893 100644 --- a/apps/ios/SimpleX Service/FileProviderExtension.swift +++ b/apps/ios/SimpleX Service/FileProviderExtension.swift @@ -8,10 +8,17 @@ import FileProvider import OSLog +import SimpleXChat let logger = Logger() -var serviceListener = NSXPCListener.service() -var listenerDelegate = SimpleXFPServiceDelegate() +let serviceListener = NSXPCListener.service() +let listenerDelegate = SimpleXFPServiceDelegate() +var machMessenger = MachMessenger(FPS_MACH_PORT, callback: receivedAppMachMessage) + +func receivedAppMachMessage(_ msgId: Int32, msg: String) -> String? { + logger.debug("MachMessenger: FileProviderExtension receivedAppMachMessage \"\(msg)\" from App, replying") + return "reply from FPS to: \(msg)" +} class FileProviderExtension: NSFileProviderExtension { var fileManager = FileManager() @@ -19,6 +26,19 @@ class FileProviderExtension: NSFileProviderExtension { override init() { logger.debug("FileProviderExtension.init") super.init() + machMessenger.start() + serviceListener.delegate = listenerDelegate + + do { + let endPointData = try NSKeyedArchiver.archivedData(withRootObject: serviceListener.endpoint, requiringSecureCoding: true) + let err = machMessenger.sendMessage(APP_MACH_PORT, data: endPointData) + logger.debug("FileProviderExtension.MachMessenger.sendMessage with endpoint res \(String(describing: err), privacy: .public)") + // let res = machMessenger.sendMessageWithReply(APP_MACH_PORT, msg: "machMessenger in FileProviderExtension") + // logger.debug("FileProviderExtension MachMessenger app reply \(String(describing: res), privacy: .public)") + } catch let err { + logger.debug("FileProviderExtension.MachMessenger.sendMessage error \(String(describing: err), privacy: .public)") + } + let manager = NSFileProviderManager.default logger.debug("FileProviderExtension.init NSFileProviderManager \(manager.documentStorageURL, privacy: .public)") @@ -40,7 +60,6 @@ class FileProviderExtension: NSFileProviderExtension { } } - serviceListener.delegate = listenerDelegate Task { serviceListener.resume() } } diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 4723ed2dfd..812a47a064 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 5C1CAA652847ED13009E5C72 /* MyServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1CAA642847ED13009E5C72 /* MyServiceProtocol.swift */; }; 5C1CAA662847F5BD009E5C72 /* FPService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1CAA3B2847DE88009E5C72 /* FPService.swift */; }; 5C1CAA672848168A009E5C72 /* SimpleX Service.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5C1CAA152847C5C8009E5C72 /* SimpleX Service.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 5C1CAA6A2849119A009E5C72 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; platformFilter = ios; }; 5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; }; 5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; }; 5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260E27A30FDC00F70299 /* ChatView.swift */; }; @@ -138,6 +139,13 @@ remoteGlobalIDString = 5C1CAA142847C5C8009E5C72; remoteInfo = "SimpleX Service"; }; + 5C1CAA6C2849119A009E5C72 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5CA059BE279559F40002BEB4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5CE2BA672845308900EC33A6; + remoteInfo = SimpleXChat; + }; 5CA059D8279559F40002BEB4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5CA059BE279559F40002BEB4 /* Project object */; @@ -337,6 +345,7 @@ buildActionMask = 2147483647; files = ( 5C1CAA172847C5C8009E5C72 /* UniformTypeIdentifiers.framework in Frameworks */, + 5C1CAA6A2849119A009E5C72 /* SimpleXChat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -737,6 +746,7 @@ buildRules = ( ); dependencies = ( + 5C1CAA6D2849119A009E5C72 /* PBXTargetDependency */, ); name = "SimpleX Service"; productName = "SimpleX Service"; @@ -1136,6 +1146,12 @@ target = 5C1CAA142847C5C8009E5C72 /* SimpleX Service */; targetProxy = 5C1CAA682848168A009E5C72 /* PBXContainerItemProxy */; }; + 5C1CAA6D2849119A009E5C72 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = ios; + target = 5CE2BA672845308900EC33A6 /* SimpleXChat */; + targetProxy = 5C1CAA6C2849119A009E5C72 /* PBXContainerItemProxy */; + }; 5CA059D9279559F40002BEB4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 5CA059C9279559F40002BEB4 /* SimpleX (iOS) */; @@ -1203,6 +1219,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 51; DEVELOPMENT_TEAM = 5NN7GUYB6T; + ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "SimpleX Service/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "SimpleX Service"; @@ -1231,6 +1248,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 51; DEVELOPMENT_TEAM = 5NN7GUYB6T; + ENABLE_BITCODE = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "SimpleX Service/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "SimpleX Service"; diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index 92573e0354..1654762093 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -17,6 +17,8 @@ public let NSE_MACH_PORT = "\(APP_GROUP_NAME).nse" as CFString public let APP_MACH_PORT = "\(APP_GROUP_NAME).app" as CFString +public let FPS_MACH_PORT = "\(APP_GROUP_NAME).fps" as CFString + func getGroupDefaults() -> UserDefaults? { UserDefaults(suiteName: APP_GROUP_NAME) } @@ -55,6 +57,7 @@ public class MachMessenger { case sndTimeout case rcvTimeout case portInvalid + case portBecameInvalid case sendError(Int32) case msgError } @@ -75,7 +78,7 @@ public class MachMessenger { case kCFMessagePortSendTimeout: return .sndTimeout case kCFMessagePortReceiveTimeout: return .rcvTimeout case kCFMessagePortIsInvalid: return .portInvalid - case kCFMessagePortBecameInvalidError: return .portInvalid + case kCFMessagePortBecameInvalidError: return .portBecameInvalid default: return .sendError(code) } } @@ -104,6 +107,17 @@ public class MachMessenger { } } + public func sendMessage(_ remotePortName: CFString, msgId: Int32 = 0, data: Data) -> SendError? { + logger.debug("MachMessenger.sendMessage") + if let port = createRemotePort(remotePortName) { + logger.debug("MachMessenger.sendMessage: sending...") + return sendMessage(port, msgId: msgId, data: data) + } else { + logger.debug("MachMessenger.sendMessage: no remote port") + return .portInvalid + } + } + public func sendMessageWithReply(_ remotePortName: CFString, msgId: Int32 = 0, msg: String) -> Result { logger.debug("MachMessenger.sendMessageWithReply") if let port = createRemotePort(remotePortName) { @@ -149,14 +163,17 @@ public class MachMessenger { private func sendMessage(_ remotePort: CFMessagePort, msgId: Int32 = 0, msg: String) -> SendError? { if let data = msg.data(using: .utf8) { logger.debug("MachMessenger sendMessage") - let msgData = data as CFData - let code = CFMessagePortSendRequest(remotePort, msgId, msgData, MACH_SEND_TIMEOUT, 0, nil, nil) - logger.debug("MachMessenger sendMessage \(code)") - return MachMessenger.sendError(code) + return sendMessage(remotePort, msgId: msgId, data: data) } return .msgError } + private func sendMessage(_ remotePort: CFMessagePort, msgId: Int32 = 0, data: Data) -> SendError? { + let code = CFMessagePortSendRequest(remotePort, msgId, data as CFData, MACH_SEND_TIMEOUT, 0, nil, nil) + logger.debug("MachMessenger sendMessage \(code)") + return MachMessenger.sendError(code) + } + private func sendMessageWithReply(_ remotePort: CFMessagePort, msgId: Int32 = 0, msg: String) -> Result { if let data = msg.data(using: .utf8) { let msgData = data as CFData