capnproto / capnproto-rust

Cap'n Proto for Rust
MIT License
2.04k stars 221 forks source link

Using capnproto with fd's as capabilities #204

Open gilhooleyd opened 3 years ago

gilhooleyd commented 3 years ago

Hello!

I'm just starting to use capnproto for a hobby project and I really like it so far. I have some questions about things that aren't documented as much.

Background: I'm interested in writing a more capability-based OS, and CapProto seems like a great candidate for the IPC. I want to get the groundwork down in Unix though, and so I'm currently using UnixDomain sockets as a way to have bi-directional sockets that can pass both data and capabilities (unix fd's).

Question:

Is it possible to specify a "capability" like a unix Fd in the capnproto schema? How then does the generated code pass these Fd's? It looks like I can pass my own implementations for InputStream, OutputStream to twoparty::Vatnework, but the Fd's need to be treated separately from the other data. Should I be looking lower in the code than twoparty? I tried looking at ClientHook and the underlying capproto::Capabilities, but it didn't seem obvious where this could be implemented.

zenhack commented 3 years ago

Quoting David Gilhooley (2020-11-24 11:06:34)

Is it possible to specify a "capability" like a unix Fd in the capnproto schema? How then does the generated code pass these Fd's? It looks like I can pass my own implementations for InputStream, OutputStream to twoparty::Vatnework, but the Fd's need to be treated separately from the other data. Should I be looking lower in the code than twoparty? I tried looking at ClientHook and the underlying capproto::Capabilities, but it didn't seem obvious where this could be implemented.

Afaik only the C++ implementation supports this, but the rpc schema does provide a mechanism for this:

https://github.com/capnproto/capnproto/blob/307a94bcc24df112b5ea2373175debfa5fad596f/c%2B%2B/src/capnp/rpc.capnp#L992

I don't think there's any way to do this with the Rust implementation currently (@dwrensha, correct me if I'm wrong).

gilhooleyd commented 3 years ago

Thanks for linking that! Yes, I was seeing this in the C++ library. I was interested in getting more familiar with Rust at the same time that I got more familiar with CapnProto.

I'd be willing to put some amount of work into getting a mechanism for this if someone could outline generally how it would be done in the codebase. I imagine that once's there's a space for a "OS Identifier", it can easily be applied to a Unix Fd, or a capability on another OS.

Does the rust library use the same rpc.capnp file? Is this something that just needs to be implemented in the library? I notice that the examples for the rust library seem to be mostly networking, and not unix specific.

zenhack commented 3 years ago

Does the rust library use the same rpc.capnp file? Is this something that just needs to be implemented in the library?

Yes, rpc.capnp defines the protocol level messages used by all rpc implementations, so it's "just" a matter of having the rust library actually do something with that field.

I notice that the examples for the rust library seem to be mostly networking, and not unix specific.

Without this feature, the rpc layer doesn't really care too much about the transport -- it just needs a way to push bytes around. You can speak capnp rpc over a unix domain socket as well. The C++ implementation has an additional interface kj::AsyncCapabilityStream which supports passing fds as well, presumably we'd want an analogous trait.

I'm less familiar with the internals of the Rust implementation than I am some of the others; @dwrensha is probably better able to point to specific bits of the code.