annotate win32-mingw/include/capnp/rpc-twoparty.capnp @ 159:f4b37539fcc7

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