chromium/mojo/proxy/README.md

Mojo Proxy
====
The Mojo Proxy is a simple standalone service which can act as a bridge between
a process using Mojo+ipcz and a process running only the legacy Mojo Core
implementation. Currently the service is only supported on POSIX systems.

Usage
----
On POSIX systems, a host process normally sends an invitation to some other
client or service (the "target" herein) via a Unix socket. The invitation has
one or more pipe attachments associated with it. The target accepts this
invitation from a peer socket and extracts its pipe attachments, thus
bootstrapping Mojo IPC for the target:

```c++
mojo::ScopedMessagePipeHandle ConnectToTarget(
    mojo::PlatformChannelEndpoint endpoint) {
  mojo::OutgoingInvitation invitation;
  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe("pipe!");
  mojo::OutgoingInvitation::Send(std::move(invitation), {},
                                 std::move(endpoint));
  return pipe;
}
```

If the host process is running Mojo+ipcz but the target is not, the host can
instead launch an instance of this proxy executable to act as an intermediary.

This will require the host to allocate an additional socket pair for
communication with the proxy.

Also note the proxy should be launched from the host via fork+exec so that it
can inherit the necessary file descriptors.

```c++
mojo::ScopedMessagePipeHandle ConnectToLegacyTarget(
    mojo::PlatformChannelEndpoint endpoint) {
  // Create a new channel for host<->proxy communication.
  mojo::PlatformChannel proxy_channel;

  // Somehow launch the `mojo_proxy` instance via fork+exec, inheriting the
  // two passed descriptors. `target_fd` must be identified by
  // `--legacy-client-fd=N` and `proxy_fd` must be identified by
  // `--host-ipcz-transport-fd=N` on the `mojo_proxy` command line.
  // The attachment name "pipe!" must be passed via `--attachment-name`.
  base::ScopedFD target_fd = endpoint.TakePlatformHandle().TakeFD();
  base::ScopedFD proxy_fd =
      proxy_channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD();
  LaunchProxy(std::move(target_fd), std::move(proxy_fd), "pipe!");

  // Otherwise invitation looks the same as before, except we're sending it
  // over a different endpoint which goes through the proxy.
  mojo::OutgoingInvitation invitation;
  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe("pipe!");
  mojo::OutgoingInvitation::Send(std::move(invitation), {},
                                 proxy_channel.TakeLocalEndpoint());
  return pipe;
}
```

For applications which attach multiple pipes to an invitation, only numeric
pipe names are supported. They can be passed to the proxy using
`--numeric-attachment-names=0,1,2` instead of using `--attachment-name`.

Finally, if the host is not a broker process it must also pass
`--inherit-ipcz-broker` to the proxy.