Difference between revisions of "LightMessaging"

From iPhone Development Wiki
Jump to: navigation, search
(Including this in your project)
m (The Callback)
 
(37 intermediate revisions by 3 users not shown)
Line 1: Line 1:
LightMessaging is a sexy header-only [[IPC]] framework by the grate god [[User:Rpetrich|Ryan Petrich]]. According to its [https://github.com/rpetrich/LightMessaging GitHub page], it is a "simple low-level replacement for CFMessagePort". It is usually used as an API to [[RocketBootstrap]].
+
LightMessaging is a work-in-progress [[IPC|inter-process communication]] header-only library by [[User:Rpetrich|Ryan Petrich]]. According to its [https://github.com/rpetrich/LightMessaging GitHub page], it is a "simple low-level replacement for CFMessagePort".
  
== Why should I use this? ==
+
== How to use this library ==
  
* Ryan Petrich.
+
Headers are available from [https://github.com/rpetrich/LightMessaging LightMessaging's GitHub project]. If using Theos, place the headers in <code>$THEOS/include/LightMessaging</code>.
* Everyone else is using it.
 
  
== Including this in your project ==
+
=== Include directive ===
  
Grab the headers from [https://github.com/rpetrich/LightMessaging rpetrich/LightMessaging], and <source lang="objc">#import <LightMessaging/LightMessaging.h></source>. In most use cases, be sure to build your project with RocketBootstrap as a dependency.
+
<source lang="objc">
 +
#import <LightMessaging/LightMessaging.h>
 +
</source>
 +
 
 +
=== RocketBootstrap ===
 +
 
 +
LightMessaging uses RocketBootstrap by default, so be sure to have it set up ([[RocketBootstrap#How_to_use_this_library|instructions here]]). To have LightMessaging '''''not''''' use RBS, add the following directive before including the LM header:
  
== Server ==
+
<source lang="objc">
 +
#define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0
 +
</source>
  
It is recommended that this is only done in SpringBoard.
+
=== Timeouts ===
  
=== Starting the Server ===
+
Use this directive (before including the LM header) to set the timeout:
  
 
<source lang="objc">
 
<source lang="objc">
LMStartService("net.iphonedevwiki.some.server", CFRunLoopGetCurrent(), (CFMachPortCallBack)some_callback);
+
#define LIGHTMESSAGING_TIMEOUT 500 // 500 ms timeout
 
</source>
 
</source>
 +
 +
== Server ==
 +
 +
This must be done in a non-sandboxed process. Typically, this is done in [[SpringBoard.app|SpringBoard]] or a ''non-sandboxed'' [[Daemons|daemon]]. If you put the server anywhere other than SpringBoard, then you must register the service in SpringBoard using <code>rocketbootstrap_unlock</code>. [[RocketBootstrap#Usage_notes|More info here]].
 +
 +
'''Disclaimer''': The server interface is not finished yet; it may change in a future version.
  
 
=== The Callback ===
 
=== The Callback ===
  
 
<source lang="objc">
 
<source lang="objc">
void some_callback(CFMachPortRef port,
+
void some_callback(CFMachPortRef port, LMMessage *message, CFIndex size, void *info) {
                        LMMessage *request,
+
// get the reply port
                        CFIndex size,
+
mach_port_t replyPort = message->head.msgh_remote_port;
                        void *info)
+
 
{
+
// Check validity of message
    // get the reply port
+
if (!LMDataWithSizeIsValidMessage(message, size)) {
    mach_port_t replyPort = request->head.msgh_remote_port;
+
LMSendReply(replyPort, NULL, 0);
    // sanity check
+
LMResponseBufferFree((LMResponseBuffer *)message);
    if(size < sizeof(LMMessage)) {
+
return;
        LMSendReply(replyPort, NULL, 0);
+
}
        LMResponseBufferFree((LMResponseBuffer *)request);
 
        return;
 
    }
 
 
      
 
      
    // get the data you recieved
+
// Get the data you received
    void *data = LMMessageGetData(request);
+
void *data = LMMessageGetData(message);
 +
size_t length = LMMessageGetDataLength(message);
 +
// Make it into a CFDataRef object
 +
CFDataRef cfdata = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)data ?: (const UInt8 *)&data, length, kCFAllocatorNull);
  
    // send some data back
+
// Send some data back
    const char *msg = "lol";
+
const char *msg = "lol";
    LMSendReply(replyPort, msg, strlen(msg) + 1);
+
LMSendReply(replyPort, msg, strlen(msg) + 1);
  
    // free the response buffer??
+
// Free the CFDataRef object
    LMResponseBufferFree((LMResponseBuffer *)request);
+
if (cfdata) {
 +
CFRelease(cfdata);
 +
}
 +
// Free the response buffer
 +
LMResponseBufferFree((LMResponseBuffer *)message);
 
}
 
}
 +
</source>
 +
 +
=== Starting the Server ===
 +
 +
<source lang="objc">
 +
LMStartService("net.iphonedevwiki.some.server", CFRunLoopGetCurrent(), (CFMachPortCallBack)some_callback);
 
</source>
 
</source>
  
 
== Client ==
 
== Client ==
  
This can be put literally anywhere.
+
This can be run anywhere; like a command line program, sandboxed process, daemon, etc.
  
 
<source lang="objc">
 
<source lang="objc">
 
// setup connection
 
// setup connection
 
LMConnection connection = {
 
LMConnection connection = {
    MACH_PORT_NULL,
+
MACH_PORT_NULL,
    "net.iphonedevwiki.some.server"
+
"net.iphonedevwiki.some.server"
 
};
 
};
  
Line 64: Line 87:
 
const char *msg = "lol wtf";
 
const char *msg = "lol wtf";
 
SInt32 messageId = 0x1111; // this is arbitrary i think
 
SInt32 messageId = 0x1111; // this is arbitrary i think
LMConnectionSendTwoWay(connection, messageId, msg, strlen(msg) + 1, &buffer);
+
LMConnectionSendTwoWay(&connection, messageId, msg, strlen(msg) + 1, &buffer);
 
LMMessage *response = &(buffer.message);
 
LMMessage *response = &(buffer.message);
  
 
// do whatever you want !!!!
 
// do whatever you want !!!!
 
const char *data = LMMessageGetData(response);
 
const char *data = LMMessageGetData(response);
 +
 +
//cleanup
 +
LMResponseBufferFree(&buffer);
 
</source>
 
</source>
  
== ConsumeInteger / ConsumePropertyList / etc ==
+
== Type helpers ==
 
 
There are some cool helper functions for if you want to send Images / PropertyLists / etc instead of just strings. Look at the header file or other examples to see how to use them.
 
  
 +
There are some cool helper functions for if you want to send Images / PropertyLists / etc instead of just strings. Look at the [https://github.com/rpetrich/LightMessaging/blob/master/LightMessaging.h header file] or other examples to see how to use them.
  
== References ==
+
''(this section should be expanded)''
  
=== Working, Digestible Example Code ===
+
== Examples ==
  
* [https://github.com/r-plus/libcanopenurl/blob/master/LCCanOpenURL.x libcanopenurl] (client and server are in the same file)
+
* [https://github.com/r-plus/libcanopenurl/blob/master/LCCanOpenURL.x libcanopenurl]
* Lucy ([https://github.com/rweichler/lucy/blob/master/client/liblucy.c client], [https://github.com/rweichler/lucy/blob/master/server/springboard.m server])
+
* [https://github.com/rpetrich/AppList/blob/master/ALApplicationList.x AppList]
 +
* [https://github.com/a3tweaks/Flipswitch/blob/master/FSSwitchMainPanel.m#L750 FlipSwitch]
  
=== From rpetrich himself ===
+
== External links ==
  
 
* [https://rpetri.ch/jbcon2016/JailbreakCon2016.pdf rpetrich's JailbreakCon 2016 keynote on IPC]
 
* [https://rpetri.ch/jbcon2016/JailbreakCon2016.pdf rpetrich's JailbreakCon 2016 keynote on IPC]
 
* [https://github.com/rpetrich/LightMessaging/blob/master/LightMessaging.h LightMessaging.h]
 
* [https://github.com/rpetrich/LightMessaging/blob/master/LightMessaging.h LightMessaging.h]
 +
 +
{{Navbox Library}}
 +
 +
[[Category:Directories in /Library]]

Latest revision as of 19:00, 24 March 2017

LightMessaging is a work-in-progress inter-process communication header-only library by Ryan Petrich. According to its GitHub page, it is a "simple low-level replacement for CFMessagePort".

How to use this library

Headers are available from LightMessaging's GitHub project. If using Theos, place the headers in $THEOS/include/LightMessaging.

Include directive

#import <LightMessaging/LightMessaging.h>

RocketBootstrap

LightMessaging uses RocketBootstrap by default, so be sure to have it set up (instructions here). To have LightMessaging not use RBS, add the following directive before including the LM header:

#define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0

Timeouts

Use this directive (before including the LM header) to set the timeout:

#define LIGHTMESSAGING_TIMEOUT 500 // 500 ms timeout

Server

This must be done in a non-sandboxed process. Typically, this is done in SpringBoard or a non-sandboxed daemon. If you put the server anywhere other than SpringBoard, then you must register the service in SpringBoard using rocketbootstrap_unlock. More info here.

Disclaimer: The server interface is not finished yet; it may change in a future version.

The Callback

void some_callback(CFMachPortRef port, LMMessage *message, CFIndex size, void *info) {
	// get the reply port
	mach_port_t replyPort = message->head.msgh_remote_port;

	// Check validity of message
	if (!LMDataWithSizeIsValidMessage(message, size)) {
		LMSendReply(replyPort, NULL, 0);
		LMResponseBufferFree((LMResponseBuffer *)message);
		return;
	}
    
	// Get the data you received
	void *data = LMMessageGetData(message);
	size_t length = LMMessageGetDataLength(message);
	// Make it into a CFDataRef object
	CFDataRef cfdata = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)data ?: (const UInt8 *)&data, length, kCFAllocatorNull);

	// Send some data back
	const char *msg = "lol";
	LMSendReply(replyPort, msg, strlen(msg) + 1);

	// Free the CFDataRef object
	if (cfdata) {
		CFRelease(cfdata);
	}
	// Free the response buffer
	LMResponseBufferFree((LMResponseBuffer *)message);
}

Starting the Server

LMStartService("net.iphonedevwiki.some.server", CFRunLoopGetCurrent(), (CFMachPortCallBack)some_callback);

Client

This can be run anywhere; like a command line program, sandboxed process, daemon, etc.

// setup connection
LMConnection connection = {
	MACH_PORT_NULL,
	"net.iphonedevwiki.some.server"
};

//send message
LMResponseBuffer buffer;
const char *msg = "lol wtf";
SInt32 messageId = 0x1111; // this is arbitrary i think
LMConnectionSendTwoWay(&connection, messageId, msg, strlen(msg) + 1, &buffer);
LMMessage *response = &(buffer.message);

// do whatever you want !!!!
const char *data = LMMessageGetData(response);

//cleanup
LMResponseBufferFree(&buffer);

Type helpers

There are some cool helper functions for if you want to send Images / PropertyLists / etc instead of just strings. Look at the header file or other examples to see how to use them.

(this section should be expanded)

Examples

External links