Hi there. I guess the answer should be obvious and I'm just blind not to see it in the docs and sample code, but find it, alas, I failed.
How does one use XPC just for IPC, without exploiting XPC Services? As Quinn points out in
you can use XPC in other scenarios; and the one of mine is really very plain: I just have got an application, which should behave as an XPC server; and a command-line executable (it happens to be a Mozilla NMH, but I believe that's rather irrelevant), which — when launched — should connect to the app and communicate with it. Normally, I would use Distributed Objects for that; nevertheless, this time security is important, and thus I would prefer to exploit the modern and secure communication channel, which allows me to make sure that the client tool signature checks, etc.
Based on the documentation and code samples, I have tried at the server side
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.listener=[[NSXPCListener alloc] initWithMachServiceName:MyXPCName];
self.listener.delegate=self;
[self.listener resume];
}
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
... ... unimportant, for it never gets called ... ...
and at the client side
NSXPCConnection *proxy=[[NSXPCConnection alloc] initWithMachServiceName:MyXPCName options:0];
proxy.remoteObjectInterface=[NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)];
proxy.invalidationHandler = ^{ NSLog(@"### Invalidated"); };
proxy.interruptionHandler=^{ NSLog(@"### Interrupted"); };
[proxy resume];
id server=[proxy remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
NSLog(@"### Error: %@",error);
}];
[server testService2WithReply:^(NSString *reply) { NSLog(@"Got answer (%@)",reply); }]; // part of MyXPCProtocol
but it does not seem to work: my server's listener:shouldAcceptNewConnection: method gets never called, and the client — regardless whether the server runs or not! — invalidates the connexion as soon as I try to send the testService2WithReply: message.
It sort of looks like the problem might be at the server side which probably does not publish the listener name properly, for when I try to NSLog(@"%@",self.listener), I get something like “<NSXPCListener: 0x7fedb974c990> service: (null)” (contrariwise, at the client side, logging out the proxy shows something like “<NSXPCConnection: 0x100500eb0> connection to service named cz.ocs.XPCT1.test”).
My server application Info.plist contains
<key>XPCService</key>
<dict>
<key>JoinExistingSession</key>
<true/>
<key>ServiceType</key>
<string>Application</string>
</dict>
(I have tried also without JoinExistingSession, in vain.) Both the application and client are properly signed, codesign confirms that both Designated Requirements are satisfied and both the TeamIdentifiers match. The server application is not sandboxed.
Would be very glad if someone can point me to a proper documentation or code sample how to do this. All docs and code samples I managed to find explained how to use properly the launchd-based XPC Services, which I do not need here at all. Thanks a lot!
How does one use XPC just for IPC, without exploiting XPC Services?
One does not. XPC connections are always mediated via
launchd
.
I just have got an application, which should behave as an XPC server; and a command-line executable … which … should connect to the app and communicate with it.
This arrangement isn’t supported by XPC because it runs it’s a layering inversion. Applications use services, they don’t provide them. XPC does support XPC Services, which allows you to break up your app into components that provide services (the XPC Services) and components that use them (everything else), but this doesn’t work well for your scenario due to namespace issues. Specifically,
launchd
sets up a per-application namespace where it registers each XPC Service in that app, but your command line tool is running outside of that namespace.
I only know of one way for an app to provide an XPC service (note the lower case) that’s visible to a command line tool, and that’s via an XPC login item (as illustrated by the AppSandboxLoginItemXPCDemo sample code). Due to the way these are implemented the XPC service provided by the login item is published to the entire GUI session.
Clearly this is a bit of a hack, and I encourage you to file an enhancement request for the features you need. Be aware, however, that a request to allow an app to publish an arbitrary XPC service is likely to be rejected. You could, however, imagine a way for an app to include an XPC Service with a wider visibility, possibly with code signing requirements imposed on the clients of such a service.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
—
WWDC runs Mon, 4 Jun through to Fri, 8 Jun. During that time all of DTS will be at the conference, helping folks out face-to-face.