How do I detect when a remote capability that is passed to 3rd-party is released by 3rd-party?

23 views
Skip to first unread message

Christian Wendt

unread,
Jun 19, 2020, 10:04:12 AM6/19/20
to Cap'n Proto
Hi,

I am relative new to Cap'n Proto and completely lost with one issue:

There is one server with a certain capability. This capability is sent to a 2nd server, which stores the capability in a directory. A 3rd server queries the directory and accesses the capability and eventually releases it again.

I can see the release using the destructor of the first server, but I can't figure out how to detect this on the 2nd server. Any pointers are welcome.

Best regards,
Christian

Kenton Varda

unread,
Jun 19, 2020, 10:32:05 AM6/19/20
to Christian Wendt, Cap'n Proto
Hi Christian,

It's intentional that you can't see the event in this case. Eventually, we expect that the third server will be able to form a direct connection to the first server here, so the second server is cut out of the loop.

There are three design patterns you can use to get what you want here, depending on who you trust:

1) If the second server trusts the first server, it can ask the first server to create a new capability representing the same underlying object (presumably implemented as a wrapper), and then notify the second server when that capability is dropped. Then, pass the new wrapper capability off to the third server.

    interface Foo {
      getNotifyOnDropWrapper @0 (observer :Capability) -> (wrapped :Foo);
      # Returns a new capability pointing to this same object, but which also
      # holds on to `observer`, such that when the new capability is dropped,
      # `observer` is dropped too. This allows the caller to be notified when
      # the new capability is dropped.
    }

A much more complicated version of the above pattern can be found in the Sandstrom codebase: https://github.com/sandstorm-io/sandstorm/blob/master/src/sandstorm/supervisor.capnp#L222

2) If the second server trusts the third server, it can pass the third server a second capability that has no methods, and say "please drop this capability at the same time as you drop the main one". Then listen for the second capability to be dropped. Caveat: In the future where the third server forms a direct connection to the first server to handle the main capability, then these two capabilities end up on two different connections, and it's possible that one of the connections will become broken (thus automatically dropping the capability) before the other one does.

3) If the second server only trusts itself, then it must arrange to force messages to be proxied through it. The second server can construct its own wrapper around the capability, which just forwards all calls to the original capability, but whose destructor notifies the second server that the capability has been dropped. Then it sends only the wrapper to the third server. Note that the most efficient way to implement this (in C++, at least) is by using membranes; see capnp/membrane.h. "Membranes" are a fancy form of wrappers that can also transitively wrap any capabilities received *through* the original capability. Possibly more importantly for you, though, is that membranes implement proxying of calls in a more efficient way than you'd normally achieve by writing a wrapper in the obvious way.

I recommend #1 if it fits.

-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/capnproto/f1d4b082-1718-4106-b34a-136d8e78a981o%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages