annotate win32-mingw/include/capnp/rpc-twoparty.capnp @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 37d53a7e8262
children
rev   line source
Chris@50 1 # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@50 2 # Licensed under the MIT License:
Chris@50 3 #
Chris@50 4 # Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@50 5 # of this software and associated documentation files (the "Software"), to deal
Chris@50 6 # in the Software without restriction, including without limitation the rights
Chris@50 7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@50 8 # copies of the Software, and to permit persons to whom the Software is
Chris@50 9 # furnished to do so, subject to the following conditions:
Chris@50 10 #
Chris@50 11 # The above copyright notice and this permission notice shall be included in
Chris@50 12 # all copies or substantial portions of the Software.
Chris@50 13 #
Chris@50 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@50 15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@50 16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@50 17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@50 18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@50 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@50 20 # THE SOFTWARE.
Chris@50 21
Chris@50 22 @0xa184c7885cdaf2a1;
Chris@50 23 # This file defines the "network-specific parameters" in rpc.capnp to support a network consisting
Chris@50 24 # of two vats. Each of these vats may in fact be in communication with other vats, but any
Chris@50 25 # capabilities they forward must be proxied. Thus, to each end of the connection, all capabilities
Chris@50 26 # received from the other end appear to live in a single vat.
Chris@50 27 #
Chris@50 28 # Two notable use cases for this model include:
Chris@50 29 # - Regular client-server communications, where a remote client machine (perhaps living on an end
Chris@50 30 # user's personal device) connects to a server. The server may be part of a cluster, and may
Chris@50 31 # call on other servers in the cluster to help service the user's request. It may even obtain
Chris@50 32 # capabilities from these other servers which it passes on to the user. To simplify network
Chris@50 33 # common traversal problems (e.g. if the user is behind a firewall), it is probably desirable to
Chris@50 34 # multiplex all communications between the server cluster and the client over the original
Chris@50 35 # connection rather than form new ones. This connection should use the two-party protocol, as
Chris@50 36 # the client has no interest in knowing about additional servers.
Chris@50 37 # - Applications running in a sandbox. A supervisor process may execute a confined application
Chris@50 38 # such that all of the confined app's communications with the outside world must pass through
Chris@50 39 # the supervisor. In this case, the connection between the confined app and the supervisor might
Chris@50 40 # as well use the two-party protocol, because the confined app is intentionally prevented from
Chris@50 41 # talking to any other vat anyway. Any external resources will be proxied through the supervisor,
Chris@50 42 # and so to the contained app will appear as if they were hosted by the supervisor itself.
Chris@50 43 #
Chris@50 44 # Since there are only two vats in this network, there is never a need for three-way introductions,
Chris@50 45 # so level 3 is free. Moreover, because it is never necessary to form new connections, the
Chris@50 46 # two-party protocol can be used easily anywhere where a two-way byte stream exists, without regard
Chris@50 47 # to where that byte stream goes or how it was initiated. This makes the two-party runtime library
Chris@50 48 # highly reusable.
Chris@50 49 #
Chris@50 50 # Joins (level 4) _could_ be needed in cases where one or both vats are participating in other
Chris@50 51 # networks that use joins. For instance, if Alice and Bob are speaking through the two-party
Chris@50 52 # protocol, and Bob is also participating on another network, Bob may send Alice two or more
Chris@50 53 # proxied capabilities which, unbeknownst to Bob at the time, are in fact pointing at the same
Chris@50 54 # remote object. Alice may then request to join these capabilities, at which point Bob will have
Chris@50 55 # to forward the join to the other network. Note, however, that if Alice is _not_ participating on
Chris@50 56 # any other network, then Alice will never need to _receive_ a Join, because Alice would always
Chris@50 57 # know when two locally-hosted capabilities are the same and would never export a redundant alias
Chris@50 58 # to Bob. So, Alice can respond to all incoming joins with an error, and only needs to implement
Chris@50 59 # outgoing joins if she herself desires to use this feature. Also, outgoing joins are relatively
Chris@50 60 # easy to implement in this scenario.
Chris@50 61 #
Chris@50 62 # What all this means is that a level 4 implementation of the confined network is barely more
Chris@50 63 # complicated than a level 2 implementation. However, such an implementation allows the "client"
Chris@50 64 # or "confined" app to access the server's/supervisor's network with equal functionality to any
Chris@50 65 # native participant. In other words, an application which implements only the two-party protocol
Chris@50 66 # can be paired with a proxy app in order to participate in any network.
Chris@50 67 #
Chris@50 68 # So, when implementing Cap'n Proto in a new language, it makes sense to implement only the
Chris@50 69 # two-party protocol initially, and then pair applications with an appropriate proxy written in
Chris@50 70 # C++, rather than implement other parameterizations of the RPC protocol directly.
Chris@50 71
Chris@50 72 using Cxx = import "/capnp/c++.capnp";
Chris@50 73 $Cxx.namespace("capnp::rpc::twoparty");
Chris@50 74
Chris@50 75 # Note: SturdyRef is not specified here. It is up to the application to define semantics of
Chris@50 76 # SturdyRefs if desired.
Chris@50 77
Chris@50 78 enum Side {
Chris@50 79 server @0;
Chris@50 80 # The object lives on the "server" or "supervisor" end of the connection. Only the
Chris@50 81 # server/supervisor knows how to interpret the ref; to the client, it is opaque.
Chris@50 82 #
Chris@50 83 # Note that containers intending to implement strong confinement should rewrite SturdyRefs
Chris@50 84 # received from the external network before passing them on to the confined app. The confined
Chris@50 85 # app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps
Chris@50 86 # maliciously leak), but instead receives only a thing that it can pass back to the container
Chris@50 87 # later to restore the ref. See:
Chris@50 88 # http://www.erights.org/elib/capability/dist-confine.html
Chris@50 89
Chris@50 90 client @1;
Chris@50 91 # The object lives on the "client" or "confined app" end of the connection. Only the client
Chris@50 92 # knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not
Chris@50 93 # actually know how to persist capabilities at all, so use of this is unusual.
Chris@50 94 }
Chris@50 95
Chris@50 96 struct VatId {
Chris@50 97 side @0 :Side;
Chris@50 98 }
Chris@50 99
Chris@50 100 struct ProvisionId {
Chris@50 101 # Only used for joins, since three-way introductions never happen on a two-party network.
Chris@50 102
Chris@50 103 joinId @0 :UInt32;
Chris@50 104 # The ID from `JoinKeyPart`.
Chris@50 105 }
Chris@50 106
Chris@50 107 struct RecipientId {}
Chris@50 108 # Never used, because there are only two parties.
Chris@50 109
Chris@50 110 struct ThirdPartyCapId {}
Chris@50 111 # Never used, because there is no third party.
Chris@50 112
Chris@50 113 struct JoinKeyPart {
Chris@50 114 # Joins in the two-party case are simplified by a few observations.
Chris@50 115 #
Chris@50 116 # First, on a two-party network, a Join only ever makes sense if the receiving end is also
Chris@50 117 # connected to other networks. A vat which is not connected to any other network can safely
Chris@50 118 # reject all joins.
Chris@50 119 #
Chris@50 120 # Second, since a two-party connection bisects the network -- there can be no other connections
Chris@50 121 # between the networks at either end of the connection -- if one part of a join crosses the
Chris@50 122 # connection, then _all_ parts must cross it. Therefore, a vat which is receiving a Join request
Chris@50 123 # off some other network which needs to be forwarded across the two-party connection can
Chris@50 124 # collect all the parts on its end and only forward them across the two-party connection when all
Chris@50 125 # have been received.
Chris@50 126 #
Chris@50 127 # For example, imagine that Alice and Bob are vats connected over a two-party connection, and
Chris@50 128 # each is also connected to other networks. At some point, Alice receives one part of a Join
Chris@50 129 # request off her network. The request is addressed to a capability that Alice received from
Chris@50 130 # Bob and is proxying to her other network. Alice goes ahead and responds to the Join part as
Chris@50 131 # if she hosted the capability locally (this is important so that if not all the Join parts end
Chris@50 132 # up at Alice, the original sender can detect the failed Join without hanging). As other parts
Chris@50 133 # trickle in, Alice verifies that each part is addressed to a capability from Bob and continues
Chris@50 134 # to respond to each one. Once the complete set of join parts is received, Alice checks if they
Chris@50 135 # were all for the exact same capability. If so, she doesn't need to send anything to Bob at
Chris@50 136 # all. Otherwise, she collects the set of capabilities (from Bob) to which the join parts were
Chris@50 137 # addressed and essentially initiates a _new_ Join request on those capabilities to Bob. Alice
Chris@50 138 # does not forward the Join parts she received herself, but essentially forwards the Join as a
Chris@50 139 # whole.
Chris@50 140 #
Chris@50 141 # On Bob's end, since he knows that Alice will always send all parts of a Join together, he
Chris@50 142 # simply waits until he's received them all, then performs a join on the respective capabilities
Chris@50 143 # as if it had been requested locally.
Chris@50 144
Chris@50 145 joinId @0 :UInt32;
Chris@50 146 # A number identifying this join, chosen by the sender. May be reused once `Finish` messages are
Chris@50 147 # sent corresponding to all of the `Join` messages.
Chris@50 148
Chris@50 149 partCount @1 :UInt16;
Chris@50 150 # The number of capabilities to be joined.
Chris@50 151
Chris@50 152 partNum @2 :UInt16;
Chris@50 153 # Which part this request targets -- a number in the range [0, partCount).
Chris@50 154 }
Chris@50 155
Chris@50 156 struct JoinResult {
Chris@50 157 joinId @0 :UInt32;
Chris@50 158 # Matches `JoinKeyPart`.
Chris@50 159
Chris@50 160 succeeded @1 :Bool;
Chris@50 161 # All JoinResults in the set will have the same value for `succeeded`. The receiver actually
Chris@50 162 # implements the join by waiting for all the `JoinKeyParts` and then performing its own join on
Chris@50 163 # them, then going back and answering all the join requests afterwards.
Chris@50 164
Chris@50 165 cap @2 :AnyPointer;
Chris@50 166 # One of the JoinResults will have a non-null `cap` which is the joined capability.
Chris@50 167 #
Chris@50 168 # TODO(cleanup): Change `AnyPointer` to `Capability` when that is supported.
Chris@50 169 }