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