Kenton Varda wrote:
> The purpose of the EzRpc* classes is to provide a very simple API
> covering the "common case", so that people who don't want to do anything
> "custom" don't need to muck around in the details of hooking up all the
> different objects. These classes are not meant to be flexible as
> flexibility would bring with it complexity that would defeat the
> purpose. If these classes ever support encryption, it ought to be via a
> boolean "enable encryption" option which sets everything up in one
> specific recommended way, but at this point we don't have that. If you
> want to do something custom, then you're actually supposed to skip the
> EZ RPC interfaces entirely and deal directly with RpcSystem /
> TwoPartyVatNetwork.
I'm not actually using the EzRpc* classes, but I did copy out the bits
that I needed to set up the network. This includes the parts with
RpcSystem and TwoPartyVatNetwork.
> With that sorted out, the rest of your questions turn out to be mostly
> moot. TwoPartyVatNetwork just wants an AsyncIoStream. There's actually
> no need to implement AsyncIoProvider nor LowLevelAsyncIoProvider. You
> just want to implement an AsyncIoStream which supports encryption. Your
> stream implementation might wrap another, raw AsyncIoStream (i.e. from
> AsyncIoProvider) and add encryption on top of that, or it might skip
> AsyncIoProvider altogether and just wrap UnixEventPort directly, or
> maybe you'll event want to use some other event loop library and write a
> custom EventPort. These options represent different trade-offs between
> ease of integration with other KJ code vs. ease of integration with some
> other event loop framework.
TBH, what I currently want is to write as little code as possible to get
the SSL part into the connection. I certainly don't want to implement
another event loop or anything like that.
Digging some more, it indeed looks like the providers aren't actually
useful to me. But from what I understand so far, I would still have to
re-implement (meaning copy) most of what's in SocketNerwork,
SocketAddress, NetworkAddressImpl and FdConnectionReceiver, in addition
to implementing my own AsyncIoStream.
In more detail, looking at EzRpcServer:
- EzRpcServer::Impl calls SocketNetwork.parseAddress(), which calls
SocketAddress::parse() to get an array of SocketAddress instances, which
end up in a NetworkAddressImpl returned from the promise.
- EzRpcServer calls NetworkAddress::listen(), which returns a
FdConnectionReceiver.
- The accept loop calls ConnectionReceiver::accept() and gets an
AsyncStreamFd back. I wrap that one, because GnuTLS does its own
receiving and sending over the socket descriptor, so I need access to
the latter.
And there's a similar situation on the client side, although I haven't
looked at it closely yet.
Sure, I could re-implement all the address parsing, listening and
accepting, but it's all done already in async-io.c++, and I could re-use
it as-is. The only trouble is that it's all hard-wired in its private
parts, and I have no way of plugging in anything in-between that would
allow me to have ConnectionReceiver::accept() return the file descriptor
instead of an AsyncStreamFd, so that I could wrap it in my own
AsyncIoStream.
Or is there? NetworkAddressImpl uses
LowLevelIoProvider::wrapListenSocketFd() to get the ConnectionReceiver,
so if I implement my own LowLevelIoProvider and pass it to
newAsyncIoProvider(), I only have to copy the functionality that's in
FdConnectionReceiver (and therefore OwnedFileDescriptor, setNonBlocking
and setCloseOnExec). Is this how you intended this to be done?
-- Remy