annotate osx/include/capnp/rpc.h @ 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 0994c39f1e94
children
rev   line source
cannam@62 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@62 2 // Licensed under the MIT License:
cannam@62 3 //
cannam@62 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@62 5 // of this software and associated documentation files (the "Software"), to deal
cannam@62 6 // in the Software without restriction, including without limitation the rights
cannam@62 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@62 8 // copies of the Software, and to permit persons to whom the Software is
cannam@62 9 // furnished to do so, subject to the following conditions:
cannam@62 10 //
cannam@62 11 // The above copyright notice and this permission notice shall be included in
cannam@62 12 // all copies or substantial portions of the Software.
cannam@62 13 //
cannam@62 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@62 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@62 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@62 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@62 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@62 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@62 20 // THE SOFTWARE.
cannam@62 21
cannam@62 22 #ifndef CAPNP_RPC_H_
cannam@62 23 #define CAPNP_RPC_H_
cannam@62 24
cannam@62 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@62 26 #pragma GCC system_header
cannam@62 27 #endif
cannam@62 28
cannam@62 29 #include "capability.h"
cannam@62 30 #include "rpc-prelude.h"
cannam@62 31
cannam@62 32 namespace capnp {
cannam@62 33
cannam@62 34 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 35 typename ThirdPartyCapId, typename JoinResult>
cannam@62 36 class VatNetwork;
cannam@62 37 template <typename SturdyRefObjectId>
cannam@62 38 class SturdyRefRestorer;
cannam@62 39
cannam@62 40 template <typename VatId>
cannam@62 41 class BootstrapFactory: public _::BootstrapFactoryBase {
cannam@62 42 // Interface that constructs per-client bootstrap interfaces. Use this if you want each client
cannam@62 43 // who connects to see a different bootstrap interface based on their (authenticated) VatId.
cannam@62 44 // This allows an application to bootstrap off of the authentication performed at the VatNetwork
cannam@62 45 // level. (Typically VatId is some sort of public key.)
cannam@62 46 //
cannam@62 47 // This is only useful for multi-party networks. For TwoPartyVatNetwork, there's no reason to
cannam@62 48 // use a BootstrapFactory; just specify a single bootstrap capability in this case.
cannam@62 49
cannam@62 50 public:
cannam@62 51 virtual Capability::Client createFor(typename VatId::Reader clientId) = 0;
cannam@62 52 // Create a bootstrap capability appropriate for exposing to the given client. VatNetwork will
cannam@62 53 // have authenticated the client VatId before this is called.
cannam@62 54
cannam@62 55 private:
cannam@62 56 Capability::Client baseCreateFor(AnyStruct::Reader clientId) override;
cannam@62 57 };
cannam@62 58
cannam@62 59 template <typename VatId>
cannam@62 60 class RpcSystem: public _::RpcSystemBase {
cannam@62 61 // Represents the RPC system, which is the portal to objects available on the network.
cannam@62 62 //
cannam@62 63 // The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork`
cannam@62 64 // determines how to form connections between vats -- specifically, two-way, private, reliable,
cannam@62 65 // sequenced datagram connections. The RPC implementation determines how to use such connections
cannam@62 66 // to manage object references and make method calls.
cannam@62 67 //
cannam@62 68 // See `makeRpcServer()` and `makeRpcClient()` below for convenient syntax for setting up an
cannam@62 69 // `RpcSystem` given a `VatNetwork`.
cannam@62 70 //
cannam@62 71 // See `ez-rpc.h` for an even simpler interface for setting up RPC in a typical two-party
cannam@62 72 // client/server scenario.
cannam@62 73
cannam@62 74 public:
cannam@62 75 template <typename ProvisionId, typename RecipientId,
cannam@62 76 typename ThirdPartyCapId, typename JoinResult>
cannam@62 77 RpcSystem(
cannam@62 78 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 79 kj::Maybe<Capability::Client> bootstrapInterface,
cannam@62 80 kj::Maybe<RealmGateway<>::Client> gateway = nullptr);
cannam@62 81
cannam@62 82 template <typename ProvisionId, typename RecipientId,
cannam@62 83 typename ThirdPartyCapId, typename JoinResult>
cannam@62 84 RpcSystem(
cannam@62 85 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 86 BootstrapFactory<VatId>& bootstrapFactory,
cannam@62 87 kj::Maybe<RealmGateway<>::Client> gateway = nullptr);
cannam@62 88
cannam@62 89 template <typename ProvisionId, typename RecipientId,
cannam@62 90 typename ThirdPartyCapId, typename JoinResult,
cannam@62 91 typename LocalSturdyRefObjectId>
cannam@62 92 RpcSystem(
cannam@62 93 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 94 SturdyRefRestorer<LocalSturdyRefObjectId>& restorer);
cannam@62 95
cannam@62 96 RpcSystem(RpcSystem&& other) = default;
cannam@62 97
cannam@62 98 Capability::Client bootstrap(typename VatId::Reader vatId);
cannam@62 99 // Connect to the given vat and return its bootstrap interface.
cannam@62 100
cannam@62 101 Capability::Client restore(typename VatId::Reader hostId, AnyPointer::Reader objectId)
cannam@62 102 KJ_DEPRECATED("Please transition to using a bootstrap interface instead.");
cannam@62 103 // ** DEPRECATED **
cannam@62 104 //
cannam@62 105 // Restores the given SturdyRef from the network and return the capability representing it.
cannam@62 106 //
cannam@62 107 // `hostId` identifies the host from which to request the ref, in the format specified by the
cannam@62 108 // `VatNetwork` in use. `objectId` is the object ID in whatever format is expected by said host.
cannam@62 109 //
cannam@62 110 // This method will be removed in a future version of Cap'n Proto. Instead, please transition
cannam@62 111 // to using bootstrap(), which is equivalent to calling restore() with a null `objectId`.
cannam@62 112 // You may emulate the old concept of object IDs by exporting a bootstrap interface which has
cannam@62 113 // methods that can be used to obtain other capabilities by ID.
cannam@62 114
cannam@62 115 void setFlowLimit(size_t words);
cannam@62 116 // Sets the incoming call flow limit. If more than `words` worth of call messages have not yet
cannam@62 117 // received responses, the RpcSystem will not read further messages from the stream. This can be
cannam@62 118 // used as a crude way to prevent a resource exhaustion attack (or bug) in which a peer makes an
cannam@62 119 // excessive number of simultaneous calls that consume the receiver's RAM.
cannam@62 120 //
cannam@62 121 // There are some caveats. When over the flow limit, all messages are blocked, including returns.
cannam@62 122 // If the outstanding calls are themselves waiting on calls going in the opposite direction, the
cannam@62 123 // flow limit may prevent those calls from completing, leading to deadlock. However, a
cannam@62 124 // sufficiently high limit should make this unlikely.
cannam@62 125 //
cannam@62 126 // Note that a call's parameter size counts against the flow limit until the call returns, even
cannam@62 127 // if the recipient calls releaseParams() to free the parameter memory early. This is because
cannam@62 128 // releaseParams() may simply indicate that the parameters have been forwarded to another
cannam@62 129 // machine, but are still in-memory there. For illustration, say that Alice made a call to Bob
cannam@62 130 // who forwarded the call to Carol. Bob has imposed a flow limit on Alice. Alice's calls are
cannam@62 131 // being forwarded to Carol, so Bob never keeps the parameters in-memory for more than a brief
cannam@62 132 // period. However, the flow limit counts all calls that haven't returned, even if Bob has
cannam@62 133 // already freed the memory they consumed. You might argue that the right solution here is
cannam@62 134 // instead for Carol to impose her own flow limit on Bob. This has a serious problem, though:
cannam@62 135 // Bob might be forwarding requests to Carol on behalf of many different parties, not just Alice.
cannam@62 136 // If Alice can pump enough data to hit the Bob -> Carol flow limit, then those other parties
cannam@62 137 // will be disrupted. Thus, we can only really impose the limit on the Alice -> Bob link, which
cannam@62 138 // only affects Alice. We need that one flow limit to limit Alice's impact on the whole system,
cannam@62 139 // so it has to count all in-flight calls.
cannam@62 140 //
cannam@62 141 // In Sandstorm, flow limits are imposed by the supervisor on calls coming out of a grain, in
cannam@62 142 // order to prevent a grain from inundating the system with in-flight calls. In practice, the
cannam@62 143 // main time this happens is when a grain is pushing a large file download and doesn't implement
cannam@62 144 // proper cooperative flow control.
cannam@62 145 };
cannam@62 146
cannam@62 147 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 148 typename ThirdPartyCapId, typename JoinResult>
cannam@62 149 RpcSystem<VatId> makeRpcServer(
cannam@62 150 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 151 Capability::Client bootstrapInterface);
cannam@62 152 // Make an RPC server. Typical usage (e.g. in a main() function):
cannam@62 153 //
cannam@62 154 // MyEventLoop eventLoop;
cannam@62 155 // kj::WaitScope waitScope(eventLoop);
cannam@62 156 // MyNetwork network;
cannam@62 157 // MyMainInterface::Client bootstrap = makeMain();
cannam@62 158 // auto server = makeRpcServer(network, bootstrap);
cannam@62 159 // kj::NEVER_DONE.wait(waitScope); // run forever
cannam@62 160 //
cannam@62 161 // See also ez-rpc.h, which has simpler instructions for the common case of a two-party
cannam@62 162 // client-server RPC connection.
cannam@62 163
cannam@62 164 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 165 typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
cannam@62 166 typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
cannam@62 167 typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
cannam@62 168 RpcSystem<VatId> makeRpcServer(
cannam@62 169 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 170 Capability::Client bootstrapInterface, RealmGatewayClient gateway);
cannam@62 171 // Make an RPC server for a VatNetwork that resides in a different realm from the application.
cannam@62 172 // The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
cannam@62 173 // and the network's ("external") format.
cannam@62 174
cannam@62 175 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 176 typename ThirdPartyCapId, typename JoinResult>
cannam@62 177 RpcSystem<VatId> makeRpcServer(
cannam@62 178 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 179 BootstrapFactory<VatId>& bootstrapFactory);
cannam@62 180 // Make an RPC server that can serve different bootstrap interfaces to different clients via a
cannam@62 181 // BootstrapInterface.
cannam@62 182
cannam@62 183 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 184 typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
cannam@62 185 typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
cannam@62 186 typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
cannam@62 187 RpcSystem<VatId> makeRpcServer(
cannam@62 188 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 189 BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway);
cannam@62 190 // Make an RPC server that can serve different bootstrap interfaces to different clients via a
cannam@62 191 // BootstrapInterface and communicates with a different realm than the application is in via a
cannam@62 192 // RealmGateway.
cannam@62 193
cannam@62 194 template <typename VatId, typename LocalSturdyRefObjectId,
cannam@62 195 typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
cannam@62 196 RpcSystem<VatId> makeRpcServer(
cannam@62 197 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 198 SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
cannam@62 199 KJ_DEPRECATED("Please transition to using a bootstrap interface instead.");
cannam@62 200 // ** DEPRECATED **
cannam@62 201 //
cannam@62 202 // Create an RPC server which exports multiple main interfaces by object ID. The `restorer` object
cannam@62 203 // can be used to look up objects by ID.
cannam@62 204 //
cannam@62 205 // Please transition to exporting only one interface, which is known as the "bootstrap" interface.
cannam@62 206 // For backwards-compatibility with old clients, continue to implement SturdyRefRestorer, but
cannam@62 207 // return the new bootstrap interface when the request object ID is null. When new clients connect
cannam@62 208 // and request the bootstrap interface, they will get that interface. Eventually, once all clients
cannam@62 209 // are updated to request only the bootstrap interface, stop implementing SturdyRefRestorer and
cannam@62 210 // switch to passing the bootstrap capability itself as the second parameter to `makeRpcServer()`.
cannam@62 211
cannam@62 212 template <typename VatId, typename ProvisionId,
cannam@62 213 typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
cannam@62 214 RpcSystem<VatId> makeRpcClient(
cannam@62 215 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network);
cannam@62 216 // Make an RPC client. Typical usage (e.g. in a main() function):
cannam@62 217 //
cannam@62 218 // MyEventLoop eventLoop;
cannam@62 219 // kj::WaitScope waitScope(eventLoop);
cannam@62 220 // MyNetwork network;
cannam@62 221 // auto client = makeRpcClient(network);
cannam@62 222 // MyCapability::Client cap = client.restore(hostId, objId).castAs<MyCapability>();
cannam@62 223 // auto response = cap.fooRequest().send().wait(waitScope);
cannam@62 224 // handleMyResponse(response);
cannam@62 225 //
cannam@62 226 // See also ez-rpc.h, which has simpler instructions for the common case of a two-party
cannam@62 227 // client-server RPC connection.
cannam@62 228
cannam@62 229 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 230 typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
cannam@62 231 typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
cannam@62 232 typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
cannam@62 233 RpcSystem<VatId> makeRpcClient(
cannam@62 234 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 235 RealmGatewayClient gateway);
cannam@62 236 // Make an RPC client for a VatNetwork that resides in a different realm from the application.
cannam@62 237 // The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
cannam@62 238 // and the network's ("external") format.
cannam@62 239
cannam@62 240 template <typename SturdyRefObjectId>
cannam@62 241 class SturdyRefRestorer: public _::SturdyRefRestorerBase {
cannam@62 242 // ** DEPRECATED **
cannam@62 243 //
cannam@62 244 // In Cap'n Proto 0.4.x, applications could export multiple main interfaces identified by
cannam@62 245 // object IDs. The callback used to map object IDs to objects was `SturdyRefRestorer`, as we
cannam@62 246 // imagined this would eventually be used for restoring SturdyRefs as well. In practice, it was
cannam@62 247 // never used for real SturdyRefs, only for exporting singleton objects under well-known names.
cannam@62 248 //
cannam@62 249 // The new preferred strategy is to export only a _single_ such interface, called the
cannam@62 250 // "bootstrap interface". That interface can itself have methods for obtaining other objects, of
cannam@62 251 // course, but that is up to the app. `SturdyRefRestorer` exists for backwards-compatibility.
cannam@62 252 //
cannam@62 253 // Hint: Use SturdyRefRestorer<capnp::Text> to define a server that exports services under
cannam@62 254 // string names.
cannam@62 255
cannam@62 256 public:
cannam@62 257 virtual Capability::Client restore(typename SturdyRefObjectId::Reader ref)
cannam@62 258 KJ_DEPRECATED(
cannam@62 259 "Please transition to using bootstrap interfaces instead of SturdyRefRestorer.") = 0;
cannam@62 260 // Restore the given object, returning a capability representing it.
cannam@62 261
cannam@62 262 private:
cannam@62 263 Capability::Client baseRestore(AnyPointer::Reader ref) override final;
cannam@62 264 };
cannam@62 265
cannam@62 266 // =======================================================================================
cannam@62 267 // VatNetwork
cannam@62 268
cannam@62 269 class OutgoingRpcMessage {
cannam@62 270 // A message to be sent by a `VatNetwork`.
cannam@62 271
cannam@62 272 public:
cannam@62 273 virtual AnyPointer::Builder getBody() = 0;
cannam@62 274 // Get the message body, which the caller may fill in any way it wants. (The standard RPC
cannam@62 275 // implementation initializes it as a Message as defined in rpc.capnp.)
cannam@62 276
cannam@62 277 virtual void send() = 0;
cannam@62 278 // Send the message, or at least put it in a queue to be sent later. Note that the builder
cannam@62 279 // returned by `getBody()` remains valid at least until the `OutgoingRpcMessage` is destroyed.
cannam@62 280 };
cannam@62 281
cannam@62 282 class IncomingRpcMessage {
cannam@62 283 // A message received from a `VatNetwork`.
cannam@62 284
cannam@62 285 public:
cannam@62 286 virtual AnyPointer::Reader getBody() = 0;
cannam@62 287 // Get the message body, to be interpreted by the caller. (The standard RPC implementation
cannam@62 288 // interprets it as a Message as defined in rpc.capnp.)
cannam@62 289 };
cannam@62 290
cannam@62 291 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 292 typename ThirdPartyCapId, typename JoinResult>
cannam@62 293 class VatNetwork: public _::VatNetworkBase {
cannam@62 294 // Cap'n Proto RPC operates between vats, where a "vat" is some sort of host of objects.
cannam@62 295 // Typically one Cap'n Proto process (in the Unix sense) is one vat. The RPC system is what
cannam@62 296 // allows calls between objects hosted in different vats.
cannam@62 297 //
cannam@62 298 // The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork`
cannam@62 299 // determines how to form connections between vats -- specifically, two-way, private, reliable,
cannam@62 300 // sequenced datagram connections. The RPC implementation determines how to use such connections
cannam@62 301 // to manage object references and make method calls.
cannam@62 302 //
cannam@62 303 // The most common implementation of VatNetwork is TwoPartyVatNetwork (rpc-twoparty.h). Most
cannam@62 304 // simple client-server apps will want to use it. (You may even want to use the EZ RPC
cannam@62 305 // interfaces in `ez-rpc.h` and avoid all of this.)
cannam@62 306 //
cannam@62 307 // TODO(someday): Provide a standard implementation for the public internet.
cannam@62 308
cannam@62 309 public:
cannam@62 310 class Connection;
cannam@62 311
cannam@62 312 struct ConnectionAndProvisionId {
cannam@62 313 // Result of connecting to a vat introduced by another vat.
cannam@62 314
cannam@62 315 kj::Own<Connection> connection;
cannam@62 316 // Connection to the new vat.
cannam@62 317
cannam@62 318 kj::Own<OutgoingRpcMessage> firstMessage;
cannam@62 319 // An already-allocated `OutgoingRpcMessage` associated with `connection`. The RPC system will
cannam@62 320 // construct this as an `Accept` message and send it.
cannam@62 321
cannam@62 322 Orphan<ProvisionId> provisionId;
cannam@62 323 // A `ProvisionId` already allocated inside `firstMessage`, which the RPC system will use to
cannam@62 324 // build the `Accept` message.
cannam@62 325 };
cannam@62 326
cannam@62 327 class Connection: public _::VatNetworkBase::Connection {
cannam@62 328 // A two-way RPC connection.
cannam@62 329 //
cannam@62 330 // This object may represent a connection that doesn't exist yet, but is expected to exist
cannam@62 331 // in the future. In this case, sent messages will automatically be queued and sent once the
cannam@62 332 // connection is ready, so that the caller doesn't need to know the difference.
cannam@62 333
cannam@62 334 public:
cannam@62 335 // Level 0 features ----------------------------------------------
cannam@62 336
cannam@62 337 virtual typename VatId::Reader getPeerVatId() = 0;
cannam@62 338 // Returns the connected vat's authenticated VatId. It is the VatNetwork's responsibility to
cannam@62 339 // authenticate this, so that the caller can be assured that they are really talking to the
cannam@62 340 // identified vat and not an imposter.
cannam@62 341
cannam@62 342 virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override = 0;
cannam@62 343 // Allocate a new message to be sent on this connection.
cannam@62 344 //
cannam@62 345 // If `firstSegmentWordSize` is non-zero, it should be treated as a hint suggesting how large
cannam@62 346 // to make the first segment. This is entirely a hint and the connection may adjust it up or
cannam@62 347 // down. If it is zero, the connection should choose the size itself.
cannam@62 348
cannam@62 349 virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override = 0;
cannam@62 350 // Wait for a message to be received and return it. If the read stream cleanly terminates,
cannam@62 351 // return null. If any other problem occurs, throw an exception.
cannam@62 352
cannam@62 353 virtual kj::Promise<void> shutdown() override KJ_WARN_UNUSED_RESULT = 0;
cannam@62 354 // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
cannam@62 355 // returned promise resolves after shutdown is complete.
cannam@62 356
cannam@62 357 private:
cannam@62 358 AnyStruct::Reader baseGetPeerVatId() override;
cannam@62 359 };
cannam@62 360
cannam@62 361 // Level 0 features ------------------------------------------------
cannam@62 362
cannam@62 363 virtual kj::Maybe<kj::Own<Connection>> connect(typename VatId::Reader hostId) = 0;
cannam@62 364 // Connect to a VatId. Note that this method immediately returns a `Connection`, even
cannam@62 365 // if the network connection has not yet been established. Messages can be queued to this
cannam@62 366 // connection and will be delivered once it is open. The caller must attempt to read from the
cannam@62 367 // connection to verify that it actually succeeded; the read will fail if the connection
cannam@62 368 // couldn't be opened. Some network implementations may actually start sending messages before
cannam@62 369 // hearing back from the server at all, to avoid a round trip.
cannam@62 370 //
cannam@62 371 // Returns nullptr if `hostId` refers to the local host.
cannam@62 372
cannam@62 373 virtual kj::Promise<kj::Own<Connection>> accept() = 0;
cannam@62 374 // Wait for the next incoming connection and return it.
cannam@62 375
cannam@62 376 // Level 4 features ------------------------------------------------
cannam@62 377 // TODO(someday)
cannam@62 378
cannam@62 379 private:
cannam@62 380 kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
cannam@62 381 baseConnect(AnyStruct::Reader hostId) override final;
cannam@62 382 kj::Promise<kj::Own<_::VatNetworkBase::Connection>> baseAccept() override final;
cannam@62 383 };
cannam@62 384
cannam@62 385 // =======================================================================================
cannam@62 386 // ***************************************************************************************
cannam@62 387 // Inline implementation details start here
cannam@62 388 // ***************************************************************************************
cannam@62 389 // =======================================================================================
cannam@62 390
cannam@62 391 template <typename VatId>
cannam@62 392 Capability::Client BootstrapFactory<VatId>::baseCreateFor(AnyStruct::Reader clientId) {
cannam@62 393 return createFor(clientId.as<VatId>());
cannam@62 394 }
cannam@62 395
cannam@62 396 template <typename SturdyRef, typename ProvisionId, typename RecipientId,
cannam@62 397 typename ThirdPartyCapId, typename JoinResult>
cannam@62 398 kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
cannam@62 399 VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
cannam@62 400 baseConnect(AnyStruct::Reader ref) {
cannam@62 401 auto maybe = connect(ref.as<SturdyRef>());
cannam@62 402 return maybe.map([](kj::Own<Connection>& conn) -> kj::Own<_::VatNetworkBase::Connection> {
cannam@62 403 return kj::mv(conn);
cannam@62 404 });
cannam@62 405 }
cannam@62 406
cannam@62 407 template <typename SturdyRef, typename ProvisionId, typename RecipientId,
cannam@62 408 typename ThirdPartyCapId, typename JoinResult>
cannam@62 409 kj::Promise<kj::Own<_::VatNetworkBase::Connection>>
cannam@62 410 VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::baseAccept() {
cannam@62 411 return accept().then(
cannam@62 412 [](kj::Own<Connection>&& connection) -> kj::Own<_::VatNetworkBase::Connection> {
cannam@62 413 return kj::mv(connection);
cannam@62 414 });
cannam@62 415 }
cannam@62 416
cannam@62 417 template <typename SturdyRef, typename ProvisionId, typename RecipientId,
cannam@62 418 typename ThirdPartyCapId, typename JoinResult>
cannam@62 419 AnyStruct::Reader VatNetwork<
cannam@62 420 SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
cannam@62 421 Connection::baseGetPeerVatId() {
cannam@62 422 return getPeerVatId();
cannam@62 423 }
cannam@62 424
cannam@62 425 template <typename SturdyRef>
cannam@62 426 Capability::Client SturdyRefRestorer<SturdyRef>::baseRestore(AnyPointer::Reader ref) {
cannam@62 427 #pragma GCC diagnostic push
cannam@62 428 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
cannam@62 429 return restore(ref.getAs<SturdyRef>());
cannam@62 430 #pragma GCC diagnostic pop
cannam@62 431 }
cannam@62 432
cannam@62 433 template <typename VatId>
cannam@62 434 template <typename ProvisionId, typename RecipientId,
cannam@62 435 typename ThirdPartyCapId, typename JoinResult>
cannam@62 436 RpcSystem<VatId>::RpcSystem(
cannam@62 437 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 438 kj::Maybe<Capability::Client> bootstrap,
cannam@62 439 kj::Maybe<RealmGateway<>::Client> gateway)
cannam@62 440 : _::RpcSystemBase(network, kj::mv(bootstrap), kj::mv(gateway)) {}
cannam@62 441
cannam@62 442 template <typename VatId>
cannam@62 443 template <typename ProvisionId, typename RecipientId,
cannam@62 444 typename ThirdPartyCapId, typename JoinResult>
cannam@62 445 RpcSystem<VatId>::RpcSystem(
cannam@62 446 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 447 BootstrapFactory<VatId>& bootstrapFactory,
cannam@62 448 kj::Maybe<RealmGateway<>::Client> gateway)
cannam@62 449 : _::RpcSystemBase(network, bootstrapFactory, kj::mv(gateway)) {}
cannam@62 450
cannam@62 451 template <typename VatId>
cannam@62 452 template <typename ProvisionId, typename RecipientId,
cannam@62 453 typename ThirdPartyCapId, typename JoinResult,
cannam@62 454 typename LocalSturdyRefObjectId>
cannam@62 455 RpcSystem<VatId>::RpcSystem(
cannam@62 456 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 457 SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
cannam@62 458 : _::RpcSystemBase(network, restorer) {}
cannam@62 459
cannam@62 460 template <typename VatId>
cannam@62 461 Capability::Client RpcSystem<VatId>::bootstrap(typename VatId::Reader vatId) {
cannam@62 462 return baseBootstrap(_::PointerHelpers<VatId>::getInternalReader(vatId));
cannam@62 463 }
cannam@62 464
cannam@62 465 template <typename VatId>
cannam@62 466 Capability::Client RpcSystem<VatId>::restore(
cannam@62 467 typename VatId::Reader hostId, AnyPointer::Reader objectId) {
cannam@62 468 return baseRestore(_::PointerHelpers<VatId>::getInternalReader(hostId), objectId);
cannam@62 469 }
cannam@62 470
cannam@62 471 template <typename VatId>
cannam@62 472 inline void RpcSystem<VatId>::setFlowLimit(size_t words) {
cannam@62 473 baseSetFlowLimit(words);
cannam@62 474 }
cannam@62 475
cannam@62 476 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 477 typename ThirdPartyCapId, typename JoinResult>
cannam@62 478 RpcSystem<VatId> makeRpcServer(
cannam@62 479 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 480 Capability::Client bootstrapInterface) {
cannam@62 481 return RpcSystem<VatId>(network, kj::mv(bootstrapInterface));
cannam@62 482 }
cannam@62 483
cannam@62 484 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 485 typename ThirdPartyCapId, typename JoinResult,
cannam@62 486 typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
cannam@62 487 RpcSystem<VatId> makeRpcServer(
cannam@62 488 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 489 Capability::Client bootstrapInterface, RealmGatewayClient gateway) {
cannam@62 490 return RpcSystem<VatId>(network, kj::mv(bootstrapInterface),
cannam@62 491 gateway.template castAs<RealmGateway<>>());
cannam@62 492 }
cannam@62 493
cannam@62 494 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 495 typename ThirdPartyCapId, typename JoinResult>
cannam@62 496 RpcSystem<VatId> makeRpcServer(
cannam@62 497 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 498 BootstrapFactory<VatId>& bootstrapFactory) {
cannam@62 499 return RpcSystem<VatId>(network, bootstrapFactory);
cannam@62 500 }
cannam@62 501
cannam@62 502 template <typename VatId, typename ProvisionId, typename RecipientId,
cannam@62 503 typename ThirdPartyCapId, typename JoinResult,
cannam@62 504 typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
cannam@62 505 RpcSystem<VatId> makeRpcServer(
cannam@62 506 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 507 BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway) {
cannam@62 508 return RpcSystem<VatId>(network, bootstrapFactory, gateway.template castAs<RealmGateway<>>());
cannam@62 509 }
cannam@62 510
cannam@62 511 template <typename VatId, typename LocalSturdyRefObjectId,
cannam@62 512 typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
cannam@62 513 RpcSystem<VatId> makeRpcServer(
cannam@62 514 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 515 SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) {
cannam@62 516 return RpcSystem<VatId>(network, restorer);
cannam@62 517 }
cannam@62 518
cannam@62 519 template <typename VatId, typename ProvisionId,
cannam@62 520 typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
cannam@62 521 RpcSystem<VatId> makeRpcClient(
cannam@62 522 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network) {
cannam@62 523 return RpcSystem<VatId>(network, nullptr);
cannam@62 524 }
cannam@62 525
cannam@62 526 template <typename VatId, typename ProvisionId,
cannam@62 527 typename RecipientId, typename ThirdPartyCapId, typename JoinResult,
cannam@62 528 typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
cannam@62 529 RpcSystem<VatId> makeRpcClient(
cannam@62 530 VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
cannam@62 531 RealmGatewayClient gateway) {
cannam@62 532 return RpcSystem<VatId>(network, nullptr, gateway.template castAs<RealmGateway<>>());
cannam@62 533 }
cannam@62 534
cannam@62 535 } // namespace capnp
cannam@62 536
cannam@62 537 #endif // CAPNP_RPC_H_