Why does my brain keep doing this? I promise, I didn't want to think through this stuff... But I might as well write it down now. CC @Dominic @dinosaur @Piet @cryptix @keks @cel
Thoughts on ipc-based plugins
These thoughts are guided by the desire to
- move as little work into the server as possible
- move as little decision power into the server as posibble
- make the server know as little about the plugins as possible
- allow sandboxing
- provide a standard mechanism to facilitate plugin-to-plugin communication
Without the last point, all of this becomes nearly trivial, we could mostly treat plugins how we currently treat clients. But the last point is also the only one in conflict with the other goals, each proposal will inherently be about making tradeoffs between them.
This discussion will also involve the distinction between server-to-server and server-to-client, and where plugin-to-plugin fits into it. Aaand there are encoding considerations about sending short integers as rpc identifiers rather than utf8 strings.
And a final warning: I don't care at all about manifest files and what they claim regarding permissions. If you talk to another process, you might send or receive any messages (or bytes actually), no matter what some sort of manifest file says. And as for permissions: Either the other endpoints does what you asked for, or it does not. Again no ties to any sort of magical file.
Plugin-to-plugin communication
Since this is what all boils down to, I might as well start here. The basic idea is that plugins expand the range of rpcs an ssb server is capable of handling. There are a few rpcs in the core, and then it might delegate other rpcs to plugins.
Addressing plugins
I basically see two reasonable approaches for making sure that an rpc reaches the correct plugin: Anonymous plugins (or globally scoped plugins) and named plugins (or namespaced plugins).
In the case of anonymous plugins, the server would receive an rpc (which contains a well-known identifier), then check whether one of its plugins is able to handle an rpc of that identifier. In the case of named plugins, each plugin comes with a well-known identifier, and rpcs specify the plugin to which they are addressed. The server just delegates based on the identifier.
At first glance, there seems to be a big advantage of the anonymous approach: An endpoint does not need to know whether a certain rpc is provided by the core, or a plugin (or which one). But on closer examination, this does not really hold. Any rpc mechanism only works if the communicating parties agree on the same, well-known identifiers for the rpcs. But if such an agreement is necessary, then they can just as well agree on the well-known name of the plugin that implements the rpc.
But named plugins actually reduce the burden of coordinating to find well-known names. They are effectively namespaces for rpc calls, as long as two plugins use different names, they can identify their rpcs however they like, including short integer identifiers.
Anonymous plugins also need to handle partial naming conflicts. It would be unsatisfactory to reject a whole plugin just because it uses the same rpc method name as some other plugin, but everything else (e.g. first come, first served) could lead to problems where the peer expects a different plugin to handle its rpc calls.
While I described the named plugin mechanism as sending the plugin name with each rpc, that's just a conceptual model. In practice, we will want to use bpmux/muxrpc channels to bundle all communication to a specific plugin. And those automatically use short identifiers rather than having to resend the well-known name each time.
So overall, namespaced plugins are easier to coordinate between different developers, are more efficient, and leave complete freedom on how the plugin interprets what kind of rpc a message represents. In fact, the server does not care about the wire protocol of the plugin at all, the plugin could use protobufs to communicate if it wanted to.
continued in next post...