1This is a design discussion for [issue 607] 2(http://code.google.com/p/nativeclient/issues/detail?id=607). 3 4## Context: implementation in Plash 5 6In [Plash](http://plash.beasts.org), the RPC for doing an open() is fairly 7straightforward and just involves two syscalls on the same socket: 8 9* sendmsg(socket\_fd, request\_message); // Send open() request 10* recvmsg(socket\_fd, reply\_buffer); // Get result, including opened FD 11 12It is not ideal that the same bidirectional socket is used for the request and 13the reply, because doing two of these RPCs concurrently would not be safe, so 14locking is required. 15 16The code for this RPC is linked into both ld.so (since this needs to open 17libraries) and libc.so (since this exports open()). The two share the same 18socket FD. Since the RPC interface is simple, sharing is not a problem. 19 20The process is endowed with socket\_fd when it is started, so the dynamic linker 21does not have to do anything to acquire it. 22 23## Implementation in NaCl browser plugin 24 25Doing this RPC when running under the NaCl browser plugin is more complicated, 26however: 27 281) It is not directly possible for the NaCl process to send an asynchronous 29message to a Javascript object. The NaCl process can normally only invoke 30Javascript objects in a Javascript event loop turn while the browser/renderer is 31blocked waiting for a reply from NaCl. 32 33The workaround is that we can artificially induce the browser/renderer to block 34to wait for NaCl using the NPN\_PluginThreadAsyncCall message. With this, 35sending a message involves 5 IMC messages: 36 37* NaCl -> plugin: NPN\_PluginThreadAsyncCall(closure\_id) 38* plugin -> NaCl: call closure\_id 39 * NaCl -> plugin: synchronously invoke Javascript object: obj(args) 40 * plugin -> NaCl: return result of obj(args) 41* NaCl -> plugin: return from closure 42 43This does not include any result that obj(args) may wish to return 44asynchronously, which would involve further messages: 45 46* plugin -> NaCl: invoke NaCl-provided JS object: callback(result) 47* NaCl -> plugin: return result of callback 48 492) The NaCl process does not start out with a suitable socket\_fd. Instead, the 50NaCl process is started with a BoundSocket, which the plugin expects to 51imc\_connect() to twice. Hence the NaCl process has to imc\_accept() on the 52BoundSocket at least twice. 53 543) The NaCl process must perform some initialisation to indicate that it 55supports NPAPI-over-SRPC. 56 574) There are no NPobjects exported across the connection either way initially. 58Since the browser side has no way to acquire an initial NaCl-side object, 59NaCl-side would have to acquire an object from Javascript's global scope. 60 615) There are two layers of message encoding: * SRPC marshalling * NPAPI argument 62marshalling, on top of SRPC 63 646) The current NaCl-side SRPC/NPAPI library code expects to have control of 65main(). 66 67(2) and (3) make it difficult for multiple users of the connection to coexist in 68the same process. 69 70## Proposed plugin extension 71 72Add a Javascript method to the plugin object: 73 74`plugin.make_socket(callback) -> fd` 75 76This creates a socket pair. It returns an FD that can be passed to the NaCl 77process. It listens for messages sent to this FD and invokes `callback` for 78every message it receives. This is implemented by spawning a thread and doing 79NPN\_PluginThreadAsyncCall() for each message. 80 81The plugin's SRPC interface already supports sending messages to the NaCl 82process (even if not receiving messages), so we can use this to send the FD at 83startup. 84