Quinn,
Thanks for the clue. After reading the XPC guides and documentation for several hours, I think I have a thread to pull. Based on your statement, I was able to zero in on this one line in the "The NSXPCConnection API" section of Creating XPC Services:
NSXPCListenerEndpoint ... This allows a process to construct a direct communication channel between two other processes that otherwise could not see one another.
Combing through the API documentation, I eventually stumbled upon +[NSListener anonymousListener] and it's C equivelent xpc_connection_create(NULL,...). Given these gems, here how I think I can use these to connect a running client app to a (possibly priviled) helper process started by some other process:
1) Create a named, on demand, system daemon managed by launchd that uses XPC.
2) Helper: Create an anonymous XPC connection/listener. Activate (resume) the connection/listener.
3) Helper: Create an endpoint from the connection/listener.
4) Helper: Connect with the named daemon (via a second XPC connection) and send the endpoint to the deamon for safe keeping.
5) Client app: Contact the named daemon and request the helper's endpoint.
6) Client app: Create a bi-directional connection to the helper using the helper's endpoint retrieved from the daemon.
At this point, I should have a bi-directional XPC connection between my client app and the helper process, completely independent of the daemon or launchd.
If I'm correct, I'm thrilled to have found this solution and look forward to eventually replacing all of my Distributed Objects and Mach ports code with XPC in the future.
But I'm also frustrated at how long (the better part of a year) it took to discover this. The XPC document has (literally) hundreds of pages of documentation, all with a laser focus on services created and managed by launchd. I can find no mention of the ability to create arbitrary connections (save for the single vague statement quoted above) anywhere in the XPC services guides, and they never once mention "anonymous" connections or listeners.
Once I discovered the term "anonymous connection", it was easy to locate the discussion of ANONYMOUS CONNECTIONS in the xpc_connection_create(3) man page. But even that doesn't explicitely mention that the endpoint can be created by another process (not the XPC service), and passed indirectly to a third process via the named service.
The documentation, as it stands now, leaves developers in the circular sitation of being able to find the information we're looking for, but only after we know what we need to be looking for. I plan to write a bug report requesting an additional section be added to the XPC Services guide on creating anonymous conections, but I'll wait for your response first.
In the mean time, I'd like to adapt a joke: A Frenchman is flying a ballon over the English channel. A great storm overtakes him and blows him off course. He eventually crashes in a broad field. An Englishman runs up to him and says "Are you injured?" The Frenchman says "I'm fine, but where am I?" The Englishman says "You're in a ballon that's crashed in the middle of a field." The Frenchman pauses for a second and then asks "Are you an accountant?" Taken aback, the Englishman says, "Yes, I am. How did you know?" The Frenchman explains, "Because everything thing you told me was completely accurate, but didn't tell me anything I needed to know."
I would officially like to update this joke to replace "accountant" with "man page author." 🙂