Commit 743e7cec authored by Kenton Varda's avatar Kenton Varda

Add a concept of membrane trees, needed in Sandstorm.

parent 6cfe2aab
...@@ -321,13 +321,15 @@ public: ...@@ -321,13 +321,15 @@ public:
static kj::Own<ClientHook> wrap(ClientHook& cap, MembranePolicy& policy, bool reverse) { static kj::Own<ClientHook> wrap(ClientHook& cap, MembranePolicy& policy, bool reverse) {
if (cap.getBrand() == MEMBRANE_BRAND) { if (cap.getBrand() == MEMBRANE_BRAND) {
auto& otherMembrane = kj::downcast<MembraneHook>(cap); auto& otherMembrane = kj::downcast<MembraneHook>(cap);
if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { auto& rootPolicy = policy.rootPolicy();
if (&otherMembrane.policy->rootPolicy() == &rootPolicy &&
otherMembrane.reverse == !reverse) {
// Capability that passed across the membrane one way is now passing back the other way. // Capability that passed across the membrane one way is now passing back the other way.
// Unwrap it rather than double-wrap it. // Unwrap it rather than double-wrap it.
Capability::Client unwrapped(otherMembrane.inner->addRef()); Capability::Client unwrapped(otherMembrane.inner->addRef());
return ClientHook::from( return ClientHook::from(
reverse ? policy.importInternal(kj::mv(unwrapped)) reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy)
: policy.exportExternal(kj::mv(unwrapped))); : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy));
} }
} }
...@@ -339,13 +341,15 @@ public: ...@@ -339,13 +341,15 @@ public:
static kj::Own<ClientHook> wrap(kj::Own<ClientHook> cap, MembranePolicy& policy, bool reverse) { static kj::Own<ClientHook> wrap(kj::Own<ClientHook> cap, MembranePolicy& policy, bool reverse) {
if (cap->getBrand() == MEMBRANE_BRAND) { if (cap->getBrand() == MEMBRANE_BRAND) {
auto& otherMembrane = kj::downcast<MembraneHook>(*cap); auto& otherMembrane = kj::downcast<MembraneHook>(*cap);
if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { auto& rootPolicy = policy.rootPolicy();
if (&otherMembrane.policy->rootPolicy() == &rootPolicy &&
otherMembrane.reverse == !reverse) {
// Capability that passed across the membrane one way is now passing back the other way. // Capability that passed across the membrane one way is now passing back the other way.
// Unwrap it rather than double-wrap it. // Unwrap it rather than double-wrap it.
Capability::Client unwrapped(otherMembrane.inner->addRef()); Capability::Client unwrapped(otherMembrane.inner->addRef());
return ClientHook::from( return ClientHook::from(
reverse ? policy.importInternal(kj::mv(unwrapped)) reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy)
: policy.exportExternal(kj::mv(unwrapped))); : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy));
} }
} }
...@@ -489,11 +493,13 @@ Capability::Client MembranePolicy::exportInternal(Capability::Client internal) { ...@@ -489,11 +493,13 @@ Capability::Client MembranePolicy::exportInternal(Capability::Client internal) {
ClientHook::from(kj::mv(internal)), addRef(), false)); ClientHook::from(kj::mv(internal)), addRef(), false));
} }
Capability::Client MembranePolicy::importInternal(Capability::Client internal) { Capability::Client MembranePolicy::importInternal(
Capability::Client internal, MembranePolicy& exportPolicy, MembranePolicy& importPolicy) {
return kj::mv(internal); return kj::mv(internal);
} }
Capability::Client MembranePolicy::exportExternal(Capability::Client external) { Capability::Client MembranePolicy::exportExternal(
Capability::Client external, MembranePolicy& importPolicy, MembranePolicy& exportPolicy) {
return kj::mv(external); return kj::mv(external);
} }
......
...@@ -144,13 +144,22 @@ public: ...@@ -144,13 +144,22 @@ public:
// itself was originally returned by the default implementation of exportInternal(), in which // itself was originally returned by the default implementation of exportInternal(), in which
// case importInternal() is called instead. // case importInternal() is called instead.
virtual Capability::Client importInternal(Capability::Client internal); virtual MembranePolicy& rootPolicy() { return *this; }
// If two policies return the same value for rootPolicy(), then a capability imported through
// one can be exported through the other, and vice versa. `importInternal()` and
// `exportExternal()` will always be called on the root policy, passing the two child policies
// as parameters. If you don't override rootPolicy(), then the policy references passed to
// importInternal() and exportExternal() will always be references to *this.
virtual Capability::Client importInternal(
Capability::Client internal, MembranePolicy& exportPolicy, MembranePolicy& importPolicy);
// An internal capability which was previously exported is now being re-imported, i.e. a // An internal capability which was previously exported is now being re-imported, i.e. a
// capability passed out of the membrane and then back in. // capability passed out of the membrane and then back in.
// //
// The default implementation simply returns `internal`. // The default implementation simply returns `internal`.
virtual Capability::Client exportExternal(Capability::Client external); virtual Capability::Client exportExternal(
Capability::Client external, MembranePolicy& importPolicy, MembranePolicy& exportPolicy);
// An external capability which was previously imported is now being re-exported, i.e. a // An external capability which was previously imported is now being re-exported, i.e. a
// capability passed into the membrane and then back out. // capability passed into the membrane and then back out.
// //
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment