annotate win32-mingw/include/capnp/membrane.h @ 141:1b5b6dfd0d0e

Add updated build of PortAudio for OSX
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 03 Jan 2017 15:10:52 +0000
parents 38d1c0e7850b
children eccd51b72864
rev   line source
cannam@135 1 // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
cannam@135 2 // Licensed under the MIT License:
cannam@135 3 //
cannam@135 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@135 5 // of this software and associated documentation files (the "Software"), to deal
cannam@135 6 // in the Software without restriction, including without limitation the rights
cannam@135 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@135 8 // copies of the Software, and to permit persons to whom the Software is
cannam@135 9 // furnished to do so, subject to the following conditions:
cannam@135 10 //
cannam@135 11 // The above copyright notice and this permission notice shall be included in
cannam@135 12 // all copies or substantial portions of the Software.
cannam@135 13 //
cannam@135 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@135 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@135 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@135 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@135 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@135 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@135 20 // THE SOFTWARE.
cannam@135 21
cannam@135 22 #ifndef CAPNP_MEMBRANE_H_
cannam@135 23 #define CAPNP_MEMBRANE_H_
cannam@135 24 // In capability theory, a "membrane" is a wrapper around a capability which (usually) forwards
cannam@135 25 // calls but recursively wraps capabilities in those calls in the same membrane. The purpose of a
cannam@135 26 // membrane is to enforce a barrier between two capabilities that cannot be bypassed by merely
cannam@135 27 // introducing new objects.
cannam@135 28 //
cannam@135 29 // The most common use case for a membrane is revocation: Say Alice wants to give Bob a capability
cannam@135 30 // to access Carol, but wants to be able to revoke this capability later. Alice can accomplish this
cannam@135 31 // by wrapping Carol in a revokable wrapper which passes through calls until such a time as Alice
cannam@135 32 // indicates it should be revoked, after which all calls through the wrapper will throw exceptions.
cannam@135 33 // However, a naive wrapper approach has a problem: if Bob makes a call to Carol and sends a new
cannam@135 34 // capability in that call, or if Carol returns a capability to Bob in the response to a call, then
cannam@135 35 // the two are now able to communicate using this new capability, which Alice cannot revoke. In
cannam@135 36 // order to avoid this problem, Alice must use not just a wrapper but a "membrane", which
cannam@135 37 // recursively wraps all objects that pass through it in either direction. Thus, all connections
cannam@135 38 // formed between Bob and Carol (originating from Alice's original introduction) can be revoked
cannam@135 39 // together by revoking the membrane.
cannam@135 40 //
cannam@135 41 // Note that when a capability is passed into a membrane and then passed back out, the result is
cannam@135 42 // the original capability, not a double-membraned capability. This means that in our revocation
cannam@135 43 // example, if Bob uses his capability to Carol to obtain another capability from her, then send
cannam@135 44 // it back to her, the capability Carol receives back will NOT be revoked when Bob's access to
cannam@135 45 // Carol is revoked. Thus Bob can create long-term irrevocable connections. In most practical use
cannam@135 46 // cases, this is what you want. APIs commonly rely on the fact that a capability obtained and then
cannam@135 47 // passed back can be recognized as the original capability.
cannam@135 48 //
cannam@135 49 // Mark Miller on membranes: http://www.eros-os.org/pipermail/e-lang/2003-January/008434.html
cannam@135 50
cannam@135 51 #include "capability.h"
cannam@135 52
cannam@135 53 namespace capnp {
cannam@135 54
cannam@135 55 class MembranePolicy {
cannam@135 56 // Applications may implement this interface to define a membrane policy, which allows some
cannam@135 57 // calls crossing the membrane to be blocked or redirected.
cannam@135 58
cannam@135 59 public:
cannam@135 60 virtual kj::Maybe<Capability::Client> inboundCall(
cannam@135 61 uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0;
cannam@135 62 // Given an inbound call (a call originating "outside" the membrane destined for an object
cannam@135 63 // "inside" the membrane), decides what to do with it. The policy may:
cannam@135 64 //
cannam@135 65 // - Return null to indicate that the call should proceed to the destination. All capabilities
cannam@135 66 // in the parameters or result will be properly wrapped in the same membrane.
cannam@135 67 // - Return a capability to have the call redirected to that capability. Note that the redirect
cannam@135 68 // capability will be treated as outside the membrane, so the params and results will not be
cannam@135 69 // auto-wrapped; however, the callee can easily wrap the returned capability in the membrane
cannam@135 70 // itself before returning to achieve this effect.
cannam@135 71 // - Throw an exception to cause the call to fail with that exception.
cannam@135 72 //
cannam@135 73 // `target` is the underlying capability (*inside* the membrane) for which the call is destined.
cannam@135 74 // Generally, the only way you should use `target` is to wrap it in some capability which you
cannam@135 75 // return as a redirect. The redirect capability may modify the call in some way and send it to
cannam@135 76 // `target`. Be careful to use `copyIntoMembrane()` and `copyOutOfMembrane()` as appropriate when
cannam@135 77 // copying parameters or results across the membrane.
cannam@135 78 //
cannam@135 79 // Note that since `target` is inside the capability, if you were to directly return it (rather
cannam@135 80 // than return null), the effect would be that the membrane would be broken: the call would
cannam@135 81 // proceed directly and any new capabilities introduced through it would not be membraned. You
cannam@135 82 // generally should not do that.
cannam@135 83
cannam@135 84 virtual kj::Maybe<Capability::Client> outboundCall(
cannam@135 85 uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0;
cannam@135 86 // Like `inboundCall()`, but applies to calls originating *inside* the membrane and terminating
cannam@135 87 // outside.
cannam@135 88 //
cannam@135 89 // Note: It is strongly recommended that `outboundCall()` returns null in exactly the same cases
cannam@135 90 // that `inboundCall()` return null. Conversely, for any case where `inboundCall()` would
cannam@135 91 // redirect or throw, `outboundCall()` should also redirect or throw. Otherwise, you can run
cannam@135 92 // into inconsistent behavion when a promise is returned across a membrane, and that promise
cannam@135 93 // later resolves to a capability on the other side of the membrane: calls on the promise
cannam@135 94 // will enter and then exit the membrane, but calls on the eventual resolution will not cross
cannam@135 95 // the membrane at all, so it is important that these two cases behave the same.
cannam@135 96
cannam@135 97 virtual kj::Own<MembranePolicy> addRef() = 0;
cannam@135 98 // Return a new owned pointer to the same policy.
cannam@135 99 //
cannam@135 100 // Typically an implementation of MembranePolicy should also inherit kj::Refcounted and implement
cannam@135 101 // `addRef()` as `return kj::addRef(*this);`.
cannam@135 102 //
cannam@135 103 // Note that the membraning system considers two membranes created with the same MembranePolicy
cannam@135 104 // object actually to be the *same* membrane. This is relevant when an object passes into the
cannam@135 105 // membrane and then back out (or out and then back in): instead of double-wrapping the object,
cannam@135 106 // the wrapping will be removed.
cannam@135 107 };
cannam@135 108
cannam@135 109 Capability::Client membrane(Capability::Client inner, kj::Own<MembranePolicy> policy);
cannam@135 110 // Wrap `inner` in a membrane specified by `policy`. `inner` is considered "inside" the membrane,
cannam@135 111 // while the returned capability should only be called from outside the membrane.
cannam@135 112
cannam@135 113 Capability::Client reverseMembrane(Capability::Client outer, kj::Own<MembranePolicy> policy);
cannam@135 114 // Like `membrane` but treat the input capability as "outside" the membrane, and return a
cannam@135 115 // capability appropriate for use inside.
cannam@135 116 //
cannam@135 117 // Applications typically won't use this directly; the membraning code automatically sets up
cannam@135 118 // reverse membranes where needed.
cannam@135 119
cannam@135 120 template <typename ClientType>
cannam@135 121 ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy);
cannam@135 122 template <typename ClientType>
cannam@135 123 ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy);
cannam@135 124 // Convenience templates which return the same interface type as the input.
cannam@135 125
cannam@135 126 template <typename ServerType>
cannam@135 127 typename ServerType::Serves::Client membrane(
cannam@135 128 kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy);
cannam@135 129 template <typename ServerType>
cannam@135 130 typename ServerType::Serves::Client reverseMembrane(
cannam@135 131 kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy);
cannam@135 132 // Convenience templates which input a capability server type and return the appropriate client
cannam@135 133 // type.
cannam@135 134
cannam@135 135 template <typename Reader>
cannam@135 136 Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane(
cannam@135 137 Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy);
cannam@135 138 // Copy a Cap'n Proto object (e.g. struct or list), adding the given membrane to any capabilities
cannam@135 139 // found within it. `from` is interpreted as "outside" the membrane while `to` is "inside".
cannam@135 140
cannam@135 141 template <typename Reader>
cannam@135 142 Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane(
cannam@135 143 Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy);
cannam@135 144 // Like copyIntoMembrane() except that `from` is "inside" the membrane and `to` is "outside".
cannam@135 145
cannam@135 146 // =======================================================================================
cannam@135 147 // inline implementation details
cannam@135 148
cannam@135 149 template <typename ClientType>
cannam@135 150 ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy) {
cannam@135 151 return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
cannam@135 152 .castAs<typename ClientType::Calls>();
cannam@135 153 }
cannam@135 154 template <typename ClientType>
cannam@135 155 ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy) {
cannam@135 156 return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
cannam@135 157 .castAs<typename ClientType::Calls>();
cannam@135 158 }
cannam@135 159
cannam@135 160 template <typename ServerType>
cannam@135 161 typename ServerType::Serves::Client membrane(
cannam@135 162 kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) {
cannam@135 163 return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
cannam@135 164 .castAs<typename ServerType::Serves::Client>();
cannam@135 165 }
cannam@135 166 template <typename ServerType>
cannam@135 167 typename ServerType::Serves::Client reverseMembrane(
cannam@135 168 kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) {
cannam@135 169 return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
cannam@135 170 .castAs<typename ServerType::Serves::Client>();
cannam@135 171 }
cannam@135 172
cannam@135 173 namespace _ { // private
cannam@135 174
cannam@135 175 OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to,
cannam@135 176 kj::Own<MembranePolicy> policy, bool reverse);
cannam@135 177 OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to,
cannam@135 178 kj::Own<MembranePolicy> policy, bool reverse);
cannam@135 179 OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to,
cannam@135 180 kj::Own<MembranePolicy> policy, bool reverse);
cannam@135 181
cannam@135 182 } // namespace _ (private)
cannam@135 183
cannam@135 184 template <typename Reader>
cannam@135 185 Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane(
cannam@135 186 Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) {
cannam@135 187 return _::copyOutOfMembrane(
cannam@135 188 _::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from),
cannam@135 189 to, kj::mv(policy), true);
cannam@135 190 }
cannam@135 191
cannam@135 192 template <typename Reader>
cannam@135 193 Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane(
cannam@135 194 Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) {
cannam@135 195 return _::copyOutOfMembrane(
cannam@135 196 _::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from),
cannam@135 197 to, kj::mv(policy), false);
cannam@135 198 }
cannam@135 199
cannam@135 200 } // namespace capnp
cannam@135 201
cannam@135 202 #endif // CAPNP_MEMBRANE_H_