This is a design discussion for [issue 607] (http://code.google.com/p/nativeclient/issues/detail?id=607).
In Plash, the RPC for doing an open() is fairly straightforward and just involves two syscalls on the same socket:
It is not ideal that the same bidirectional socket is used for the request and the reply, because doing two of these RPCs concurrently would not be safe, so locking is required.
The code for this RPC is linked into both ld.so (since this needs to open libraries) and libc.so (since this exports open()). The two share the same socket FD. Since the RPC interface is simple, sharing is not a problem.
The process is endowed with socket_fd when it is started, so the dynamic linker does not have to do anything to acquire it.
Doing this RPC when running under the NaCl browser plugin is more complicated, however:
The workaround is that we can artificially induce the browser/renderer to block to wait for NaCl using the NPN_PluginThreadAsyncCall message. With this, sending a message involves 5 IMC messages:
This does not include any result that obj(args) may wish to return asynchronously, which would involve further messages:
The NaCl process does not start out with a suitable socket_fd. Instead, the NaCl process is started with a BoundSocket, which the plugin expects to imc_connect() to twice. Hence the NaCl process has to imc_accept() on the BoundSocket at least twice.
The NaCl process must perform some initialisation to indicate that it supports NPAPI-over-SRPC.
There are no NPobjects exported across the connection either way initially. Since the browser side has no way to acquire an initial NaCl-side object, NaCl-side would have to acquire an object from Javascript's global scope.
There are two layers of message encoding: * SRPC marshalling * NPAPI argument marshalling, on top of SRPC
The current NaCl-side SRPC/NPAPI library code expects to have control of main().
(2) and (3) make it difficult for multiple users of the connection to coexist in the same process.
Add a Javascript method to the plugin object:
plugin.make_socket(callback) -> fd
This creates a socket pair. It returns an FD that can be passed to the NaCl process. It listens for messages sent to this FD and invokes callback
for every message it receives. This is implemented by spawning a thread and doing NPN_PluginThreadAsyncCall() for each message.
The plugin's SRPC interface already supports sending messages to the NaCl process (even if not receiving messages), so we can use this to send the FD at startup.