Theos inter-app communication using mach ports - ios

I am trying to send data between an App and a console app (using theos) on iOS 8.
I have tried:
Application:
CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("co.test"), &message_callback, NULL, NULL);
This works fine. NSLog(#"%#", port) returns:
<CFMessagePort 0x17018bef0 [0x198094f50]>{locked = Maybe, valid = Yes, remote = No, name = co.test, source = 0x0, callout = message_callback (0x1000e979c), context = <CFMessagePort context 0x0>}
However when trying to do the same thing on the console app:
CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("co.test"),
&message_callback, NULL, NULL);
I always get the error:
*** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0xc03, name = 'co.test'
Even though I am using the same com.apple.security.application-groups entitlement for both:
<key>com.apple.security.application-groups</key>
<array>
<string>co.test</string>
</array>
Can anyone shed any light - maybe the above is a terrible approach and I am missing an easier way to accomplish my goal?
My goal is to be able to pass a NSDictionary between an app running on SpringBoard and a daemon built with theos.
Note: I have no intention of distributing this app on the app store

Application: .......CFSTR("co.test")
Console App: ... CFSTR("co.test")
You need to append an additional string to the end of your application group identifier.
Apple:
Mach port names must begin with the application group identifier, followed by a period (.), followed by a name of your choosing.
For example, if your application group’s name is Z123456789.com.example.app-group, you might create a Mach port named Z123456789.com.example.app-group.Port_of_Kobe.
CFMessagePort and sandboxing
Another crash seems to occur if you create multiple Message Ports use the same Message Port Name. Perhaps from an app with the same bundle ID or some other situation in which there should only be a single Message Port and one is already running.
I notice it when I run one version of my macOS app from /Applications/, and another via Xcode.
*** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0xcd07, name = 'XXXYYYZZZZ.MyAppGroupName'

Related

Network extension view print statements

I am implementing a NEPacketTunnelProvider and loading it from my view controller using:
var vpnManager: NETunnelProviderManager = NETunnelProviderManager()
...
let providerProtocol = NETunnelProviderProtocol()
providerProtocol.providerBundleIdentifier = "AA.BB.CC"
providerProtocol.serverAddress = "<something>"
...
self.vpnManager.localizedDescription = "My app"
self.vpnManager.protocolConfiguration = providerProtocol
self.vpnManager.isEnabled = true
self.vpnManager.connection.startVPNTunnel()
Parts marked with "..." seemed irrelevant.
My understanding (although it's really not clear in the documentation) is that when I do this, and I have a target that was created as type "NetworkExtension" with BundleId AA.BB.CC, that the extension would be loaded and executed properly. So, my understanding is that startTunnel (from NEPacketTunnelProvider) will implicitly be called from the code block above.
I put a NSLog("STARTING TUNNEL!!!!!") right at the top of the startTunnel method, but am not sure where to see that. So far, I have viewed the logs in:
Console
Window > Devices and simulators > View device logs
None of these appear to show the logs from within the extension. The problem is that the extension seems to crash before I can attach to the running process, so I have the feeling I'm just "missing" that log because I can't attach quickly enough.
Short question
How can I attach to a running network extension quickly enough so that I don't miss an NSLog that is run immediately?
The logs from Network extensions do not go to Xcode console. to see the logs from Network extension you have to follow the bellow steps.
Open the console application.
Select your iOS device running the network extension you will see all the logs from your device.
Filter the logs by Network extension target name now you will see the logs only from your network extension.
How can I attach to a running network extension quickly enough?
What I have been doing to solve this problem was, put the thread on sleep right before log statement.
sleep(60)
It will give you enough time to attach the Network Extension process for debug.

CloudKit, Failed to modify some records - Zone Not Found

I'm getting the following error.
ERROR[CKErrorDomain:2] Failed to modify some records,
<CKError 0x1c005e1e0: "Partial Failure" (1011); "Failed to modify some records";
partial errors: {
BB27A0F8-0D8A-4279-A4E6-515B4E6C5116:(MainCustomZone:__defaultOwner__) =
<CKError 0x1c0050740: "Zone Not Found" (26/2036); server message = "Zone 'MainCustomZone'
does not exist"; uuid = E4AE311D-A73F-4F8A-BAF7-1EF5082D2FA9>
}>
My app works fine on my development devices, but in testflight for my beta users they get the error above. When I use a testflight build it still works fine for me, yes I am pointing at the production conatiner in my entitlements I have set the 'com.apple.developer.icloud-container-environment' set to 'production.
I've triple checked that the I'm looking at the correct container and the zone name is spelt correctly.
I have iCloud enabled in my developer account under app id's.
I've also got Write set for authentication, in security roles for each record type.
Please can someone suggest what the problem is?
I've been researching the issue without success.
Here's some typical code to create a zone which I use.
CKFetchRecordChangesOperation *changesOperation = [[CKFetchRecordChangesOperation alloc]
initWithRecordZoneID: [self customZone]
previousServerChangeToken: previousServerChangeToken];
-(CKRecordZoneID*)customZone
{
return [[CKRecordZoneID alloc] initWithZoneName: cCUSTOM_ZONE
ownerName: CKOwnerDefaultName];
}
There is only one zone in a database - the Default zone. If your app is using any other zones, your app must create the zone before attempting to access (or write) any records in the zone.
You probably created the zone in development at some point which is why the code works there.
The screenshot is showing your private database. Every user has their own private database and you can't see the private database of other users in the dashboard. You need to create the zone via code in your app.

Changing Firebase configuration at runtime on iOS

For my project, I have 2 environments:
test
prod
and 2 localizations:
en
tr
and an app for each combination: (these names do not mirror Firebase project ids)
test_en
test_tr
prod_en
prod_tr
And I have a separate plist file for each of these apps in the project, with the names Firebase-(app_type).plist ie Firebase-test_en.plist or Firebase-prod_en.plist
I am initializing FIRApp using this way:
private func ensureLoaded() {
let options = FIROptions(contentsOfFile: Bundle.main
.path(forResource: "Firebase-\(firebaseApplicationName)", ofType: "plist"))!
if nil == FIRApp(named: firebaseApplicationName) {
FIRApp.configure(withName: firebaseApplicationName, options: options)
}
}
And it seems to work ok, until I try to actually connect to firebase database, where it says:
Firebase is not configured correctly, please call [FIRApp configure]
So my question is, how do I make firebase work where I want to dynamically change configurations? There are some other questions that describe how to change configuration based on some environment variables / compiler flags but they are all referring to changing the plist file, which changes the configuration during build time, but I want to change it dynamically during runtime. Is it supported at all, is there a way to make it work?
Thanks in advance.
I found what the problem was, we were using FIRApp.auth().currentUser somewhere in the app, which returns the auth for "default" app and since we had multiple configs, we had no notion of a "default" app, so the configuration was incomplete. I changed that to FIRAuth(app: myApp)?.currentUser and it works as expected now.

What is the format of the optionsFile for the IotFDevice class in Quarks?

The IotfDevice Class in Quarks has a constructor with an optionsFile. What is the format of this file and what are the necessary values?
The options file has five values: org, type, id, auth-method, auth-token. This is an example of mine with the values obfuscated.
[device]
org = 4pj4r4
type = rustQuark
id = rustIIa
auth-method = token
auth-token = 8jLWEY(P4SVJl5oi!V
When you register a device the set of values are issued, details and examples can be found here.
A little context.
Internet of Things Foundation (IoTf) is an infrastructure for application's to communicate with devices. IoTf requires that you register the application and all
devices that send data to the application.
Why would you use IoTf? Getting the communication setup between devices is
a pain: firewalls, retry, failover, QoS, debugging, monitoring. This is facility especially nice if you're doing a proof of concept.
For a better description of IoTf look here.

what cause error NSNetServicesErrorCode = "-72000"?

i create a simple browser that can load a local file using UIWebview. At first,when i try to preview a html file, the uiwebview can load the source file and preview it. But after i minimize the app (the app enter background), and then open the app again, i've got this error :
Error Dict: {
NSNetServicesErrorCode = "-72000";
NSNetServicesErrorDomain = 10;
}
and after that, the uiwebview can not load the source file, when i log the error in (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error, it shows this message :
Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo=0x53d610 {NSErrorFailingURLStringKey=http://localhost:9898/local/a.html?83C66B33-874C-41A7-BBF5-78D1615512DF, NSErrorFailingURLKey=http://localhost:9898/local/a.html?83C66B33-874C-41A7-BBF5-78D1615512DF, NSLocalizedDescription=Could not connect to the server., NSUnderlyingError=0x5ccaa0 "Could not connect to the server."}
the app isn't crash, but the spinning indicator is never stop.
could somebody tell me what cause this case? and how to solved it?
Thank you :)
If you look inside the NSNetServices header, you'll see the following enum that explains each error:
typedef NS_ENUM(NSInteger, NSNetServicesError) {
/* An unknown error occured during resolution or publication.
*/
NSNetServicesUnknownError = -72000L,
/* An NSNetService with the same domain, type and name was already present when the publication request was made.
*/
NSNetServicesCollisionError = -72001L,
/* The NSNetService was not found when a resolution request was made.
*/
NSNetServicesNotFoundError = -72002L,
/* A publication or resolution request was sent to an NSNetService instance which was already published or a search request was made of an NSNetServiceBrowser instance which was already searching.
*/
NSNetServicesActivityInProgress = -72003L,
/* An required argument was not provided when initializing the NSNetService instance.
*/
NSNetServicesBadArgumentError = -72004L,
/* The operation being performed by the NSNetService or NSNetServiceBrowser instance was cancelled.
*/
NSNetServicesCancelledError = -72005L,
/* An invalid argument was provided when initializing the NSNetService instance or starting a search with an NSNetServiceBrowser instance.
*/
NSNetServicesInvalidError = -72006L,
/* Resolution of an NSNetService instance failed because the timeout was reached.
*/
NSNetServicesTimeoutError = -72007L,
};
You're getting a service collision error, which means that a net service with the same domain, type, and name are already publishing their service on your network.
In general, I always consult the header file for error codes. They're nearly always assigned by an enum value, and the enum usually has a much more descriptive name than the number used.
The problem seems to be the host you are trying to connect to: http://localhost:9898/local/[..]
Localhost on your computer is your computer, localhost on your ipad is your ipad - for testing use resolvable domain name or ip address.
Sergiu Todirascu's comment in the question solved it for me. The Mac Sandbox was causing this, I had to turn on Networking, in my case Incoming and Outgoing network checkboxes, in the entitlements tab. Creating an answer so it is more easy to see.

Resources