Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198
RocketBootstrap: Difference between revisions - iPhone Development Wiki

RocketBootstrap: Difference between revisions

From iPhone Development Wiki
mNo edit summary
 
(14 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Infobox Package
{{Infobox Package
|developer=[[User:Rpetrich|Ryan Petrich]]
|developer=[[User:Rpetrich|Ryan Petrich]]
|version=1.0.2
|version=1.0.10~beta1
|package=com.rpetrich.rocketbootstrap
|package=com.rpetrich.rocketbootstrap
}}
}}
Line 7: Line 7:
'''RocketBootstrap''' is a library that solves a denied lookup error of [[IPC]] services on iOS 7 and above<ref>[http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_7#Inter-process_communication Updating extensions for iOS 7 - Inter-process communication]</ref>.
'''RocketBootstrap''' is a library that solves a denied lookup error of [[IPC]] services on iOS 7 and above<ref>[http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_7#Inter-process_communication Updating extensions for iOS 7 - Inter-process communication]</ref>.


''"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."''
''"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."'' <ref>[https://www.reddit.com/r/jailbreak/comments/1tv0qw/activator_182_rc1_released_with_rocketbootstrap/cebqh9p rpetrich's reddit post for RocketBootstrap's release]</ref>


== How to use this library ==
== How to use this library ==


Headers are available from [https://github.com/rpetrich/RocketBootstrap/tree/master RocketBootstrap's GitHub project] and the library can be found at <code>/usr/lib/librocketbootstrap.dylib</code> on a device where RocketBootstrap is installed. If using Theos, place the headers in <code>$THEOS/include/RocketBootstrap</code>, the library in <code>$THEOS/lib/</code> and add <code>rocketbootstrap</code> to the <code>XXX_LIBRARIES</code> Makefile variable. Further more make sure to add <code>AppSupport</code> to the <code>XXX_PRIVATE_LIBRARIES</code> and declare the interface of <code>CPDistributedMessagingCenter</code> when using the sample code.
Headers are available from [https://github.com/rpetrich/RocketBootstrap/tree/master RocketBootstrap's GitHub project] and the library can be found at <code>/usr/lib/librocketbootstrap.dylib</code> on a device where RocketBootstrap is installed. If using Theos, place the headers in <code>$THEOS/include/RocketBootstrap</code>, the library in <code>$THEOS/lib/</code>.


You should add <code>, com.rpetrich.rocketbootstrap (>= 1.0.2) | firmware (<< 7.0)</code> to your <code>Depends</code> field on your package's control file.
=== Include directive ===


== Example Usage ==
<source lang="objc">
#import <rocketbootstrap/rocketbootstrap.h>
</source>
 
=== Makefile ===
 
Add to your Makefile:
 
* <code>rocketbootstrap</code> to the <code>XXX_LIBRARIES</code> variable.
* <code>AppSupport</code> to the <code>XXX_PRIVATE_FRAMEWORKS</code> variable.
 
=== Packaging ===
 
Add to your package's control file:
 
* <code>, com.rpetrich.rocketbootstrap (>= 1.0.2) | firmware (<< 7.0)</code> to the <code>Depends</code> field.
 
== LightMessaging example ==
 
See [[LightMessaging]].
 
== CPDistributedMessagingCenter Example ==
 
Make sure you have the <tt>CPDistributedMessagingCenter</tt> interface declared.
 
=== Server inside a SpringBoard tweak ===
 
<source lang="objc">
@interface MYMessagingCenter : NSObject {
CPDistributedMessagingCenter * _messagingCenter;
}
@end
 
@implementation MYMessagingCenter
 
+ (void)load {
[self sharedInstance];
}
 
+ (instancetype)sharedInstance {
static dispatch_once_t once = 0;
__strong static id sharedInstance = nil;
dispatch_once(&once, ^{
sharedInstance = [self new];
});
return sharedInstance;
}
 
- (instancetype)init {
if ((self = [super init])) {
_messagingCenter = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
// apply rocketbootstrap regardless of iOS version (via rpetrich)
rocketbootstrap_distributedmessagingcenter_apply(_messagingCenter);
 
[_messagingCenter runServerOnCurrentThread];
[_messagingCenter registerForMessageName:@"myMessageName" target:self selector:@selector(handleMessageNamed:withUserInfo:)];
}
 
return self;
}
 
- (NSDictionary *)handleMessageNamed:(NSString *)name withUserInfo:(NSDictionary *)userInfo {
return [NSDictionary dictionaryWithObjectsAndKeys:@"key", @"object", nil];
}
 
@end
</source>
 
=== Client from sandboxed app ===
 
<source lang="objc">
static CPDistributedMessagingCenter *c = nil;
 
%ctor {
c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
rocketbootstrap_distributedmessagingcenter_apply(c);
 
// Send a message with no dictionary
[c sendMessageName:@"myMessageName" userInfo:nil];
 
// Send a message with a dictionary
NSDictionary * message = [NSDictionary dictionaryWithObjectsAndKeys: @"key", @"object", nil];
[c sendMessageName:@"myMessageName" userInfo:message];
 
// Send a message with no dictionary and receive a reply dictionary
NSDictionary * reply = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:nil];
 
// Send a message with a dictionary and receive a reply dictionary
NSDictionary * replyWithMessage = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:message];
}
</source>
 
== CFMessagePort Example ==


== Server inside a SpringBoard tweak ==
(Pilfered from [http://nshipster.com/inter-process-communication/ the NSHipster article on IPC])
 
=== Server ===


<source lang="objc">
<source lang="objc">
#import "rocketbootstrap.h"
static CFDataRef Callback(CFMessagePortRef port,
      
                          SInt32 messageID,
CPDistributedMessagingCenter *c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
                          CFDataRef data,
// apply rocketbootstrap regardless of iOS version (via rpetrich)
                          void *info)
rocketbootstrap_distributedmessagingcenter_apply(c);
{
[c runServerOnCurrentThread];
    // ...
[c registerForMessageName:@"myMessageName" target:myTarget selector:@selector(handleMessageNamed:withUserInfo:)];
}
 
%ctor {
     static CFMessagePortRef localPort =
        CFMessagePortCreateLocal(nil,
                                CFSTR("com.example.app.port.server"),
                                Callback,
                                nil,
                                nil);
 
    CFRunLoopSourceRef runLoopSource =
        CFMessagePortCreateRunLoopSource(nil, localPort, 0);
 
    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                      runLoopSource,
                      kCFRunLoopCommonModes);
 
    rocketbootstrap_cfmessageportexposelocal(localPort);
}
</source>
</source>


== Client from sandboxed app ==
=== Client ===


<source lang="objc">
<source lang="objc">
#import "rocketbootstrap.h"
void doStuff() {
      
    CFDataRef data;
CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:@"com.mycompany.myCenter"];
    SInt32 messageID = 0x1111; // Arbitrary
rocketbootstrap_distributedmessagingcenter_apply(c);
    CFTimeInterval timeout = 10.0;
[c sendMessageName:@"myMessageName" userInfo:nil]; //send an NSDictionary here to pass data
 
     CFMessagePortRef remotePort =
        rocketbootstrap_cfmessageportcreateremote(nil,
                                  CFSTR("com.example.app.port.client"));
 
    SInt32 status =
        CFMessagePortSendRequest(remotePort,
                                messageID,
                                data,
                                timeout,
                                timeout,
                                NULL,
                                NULL);
 
    if (status == kCFMessagePortSuccess) {
        // ...
    }
}
</source>
</source>


== Usage notes ==
== Usage notes ==


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.
If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call <code>rocketbootstrap_unlock</code> with the service name. Then you can run a server with the same name inside your daemon.


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.
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.
Line 62: Line 191:


* [https://github.com/rpetrich/RocketBootstrap RocketBootstrap on GitHub]
* [https://github.com/rpetrich/RocketBootstrap RocketBootstrap on GitHub]
{{Navbox Library}}


[[Category:Cydia packages]]
[[Category:Cydia packages]]
[[Category:Directories in /Library]]

Latest revision as of 15:24, 28 May 2021

RocketBootstrap
Cydia Package
Developer Ryan Petrich
Package ID com.rpetrich.rocketbootstrap
Latest Version 1.0.10~beta1


RocketBootstrap is a library that solves a denied lookup error of IPC services on iOS 7 and above[1].

"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." [2]

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/.

Include directive

#import <rocketbootstrap/rocketbootstrap.h>

Makefile

Add to your Makefile:

  • rocketbootstrap to the XXX_LIBRARIES variable.
  • AppSupport to the XXX_PRIVATE_FRAMEWORKS variable.

Packaging

Add to your package's control file:

  • , com.rpetrich.rocketbootstrap (>= 1.0.2) | firmware (<< 7.0) to the Depends field.

LightMessaging example

See LightMessaging.

CPDistributedMessagingCenter Example

Make sure you have the CPDistributedMessagingCenter interface declared.

Server inside a SpringBoard tweak

@interface MYMessagingCenter : NSObject {
	CPDistributedMessagingCenter * _messagingCenter;
}
@end

@implementation MYMessagingCenter

+ (void)load {
	[self sharedInstance];
}

+ (instancetype)sharedInstance {
	static dispatch_once_t once = 0;
	__strong static id sharedInstance = nil;
	dispatch_once(&once, ^{
		sharedInstance = [self new];
	});
	return sharedInstance;
}

- (instancetype)init {
	if ((self = [super init])) {
		_messagingCenter = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
		// apply rocketbootstrap regardless of iOS version (via rpetrich)
		rocketbootstrap_distributedmessagingcenter_apply(_messagingCenter);

		[_messagingCenter runServerOnCurrentThread];
		[_messagingCenter registerForMessageName:@"myMessageName" target:self selector:@selector(handleMessageNamed:withUserInfo:)];
	}

	return self;
}

- (NSDictionary *)handleMessageNamed:(NSString *)name withUserInfo:(NSDictionary *)userInfo {
	return [NSDictionary dictionaryWithObjectsAndKeys:@"key", @"object", nil];
}

@end

Client from sandboxed app

static CPDistributedMessagingCenter *c = nil;

%ctor {
	c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
	rocketbootstrap_distributedmessagingcenter_apply(c);

	// Send a message with no dictionary
	[c sendMessageName:@"myMessageName" userInfo:nil];

	// Send a message with a dictionary
	NSDictionary * message = [NSDictionary dictionaryWithObjectsAndKeys: @"key", @"object", nil];
	[c sendMessageName:@"myMessageName" userInfo:message];

	// Send a message with no dictionary and receive a reply dictionary
	NSDictionary * reply = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:nil];

	// Send a message with a dictionary and receive a reply dictionary
	NSDictionary * replyWithMessage = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:message];
}

CFMessagePort Example

(Pilfered from the NSHipster article on IPC)

Server

static CFDataRef Callback(CFMessagePortRef port,
                          SInt32 messageID,
                          CFDataRef data,
                          void *info)
{
    // ...
}

%ctor {
    static CFMessagePortRef localPort =
        CFMessagePortCreateLocal(nil,
                                 CFSTR("com.example.app.port.server"),
                                 Callback,
                                 nil,
                                 nil);

    CFRunLoopSourceRef runLoopSource =
        CFMessagePortCreateRunLoopSource(nil, localPort, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       runLoopSource,
                       kCFRunLoopCommonModes);

    rocketbootstrap_cfmessageportexposelocal(localPort);
}

Client

void doStuff() {
    CFDataRef data;
    SInt32 messageID = 0x1111; // Arbitrary
    CFTimeInterval timeout = 10.0;

    CFMessagePortRef remotePort =
        rocketbootstrap_cfmessageportcreateremote(nil,
                                  CFSTR("com.example.app.port.client"));

    SInt32 status =
        CFMessagePortSendRequest(remotePort,
                                 messageID,
                                 data,
                                 timeout,
                                 timeout,
                                 NULL,
                                 NULL);

    if (status == kCFMessagePortSuccess) {
        // ...
    }
}

Usage notes

If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call rocketbootstrap_unlock with the service name. Then you can run a server with the same name inside your daemon.

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).

See also

References

External links