"One common way processes communicate with each other on iOS and OS X is through a messaging system called mach ports. Each port is a channel that can either receive or send messages. There is a central registration system for these ports called bootstrap, where ports can be registered and accessed by a service name assigned to them. Recent versions of iOS restrict which names a process can access—MobileMail, MobileSafari and App Store apps are only allowed to access a very specific set of services that come with iOS. RocketBootstrap adds a secondary lookup service that doesn't restrict which processes can access which services."
How to use this library
Headers are available from RocketBootstrap's GitHub project and the library can be found at
/usr/lib/librocketbootstrap.dylib on a device where RocketBootstrap is installed. If using Theos, place the headers in
$THEOS/include/RocketBootstrap, the library in
$THEOS/lib/ and add
rocketbootstrap to the
XXX_LIBRARIES Makefile variable. Further more make sure to add
AppSupport to the
XXX_PRIVATE_FRAMEWORKS and declare the interface of
CPDistributedMessagingCenter when using the sample code.
You should add
, com.rpetrich.rocketbootstrap (>= 1.0.2) | firmware (<< 7.0) to your
Depends field on your package's control file.
Server inside a SpringBoard tweak
#import "rocketbootstrap.h" CPDistributedMessagingCenter *c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"]; // apply rocketbootstrap regardless of iOS version (via rpetrich) rocketbootstrap_distributedmessagingcenter_apply(c); [c runServerOnCurrentThread]; [c registerForMessageName:@"myMessageName" target:myTarget selector:@selector(handleMessageNamed:withUserInfo:)];
Client from sandboxed app
#import "rocketbootstrap.h" CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:@"com.mycompany.myCenter"]; rocketbootstrap_distributedmessagingcenter_apply(c); [c sendMessageName:@"myMessageName" userInfo:nil]; //send an NSDictionary here to pass data
If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call bootstrap_unlock with the service name (take the code from the rocket bootstrap header and include bootstrap.h). Then you can run a server with the same name inside your daemon. rocketbootstrap_distributedmessagingcenter_apply must still be called on both the server and on the clients. It even works for sendMessageAndReceiveReplyName.
You shouldn't be registering Mach services in sandboxed apps; RocketBootstrap allows exposing services to sandboxed apps, but can't allow exposing services from sandboxed apps without exposing a very large security flaw.
Assuming there aren't any security problems, actually calling a service that's running inside of an app from SpringBoard (which is usually what people want to do) is problematic. Backgrounding apps causes them to enter a frozen "SIGSTOP" state, which means any calls to the service running inside of the app will block indefinitely.
Even if that is suppressed, it could happen that the SpringBoard part attempts to call the service running in the app at the same time as the app is trying to call any of the usual SpringBoard services. When that happens, they deadlock. This might happen infrequently, but it's a really bad failure case in that the system just hangs. Real users will encounter it, if it's present.
You can call from a background thread (not good, it could stay alive for a long time), or use timeouts (not good, now you have to tune it and you get UI hitches) or use asynchronous code (not bad, but it's more work than you may be willing to go through).