rpc.h 27.6 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21

22
#pragma once
23

24
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25 26 27
#pragma GCC system_header
#endif

28
#include "capability.h"
29
#include "rpc-prelude.h"
30 31 32

namespace capnp {

33
template <typename VatId, typename ProvisionId, typename RecipientId,
34 35 36 37
          typename ThirdPartyCapId, typename JoinResult>
class VatNetwork;
template <typename SturdyRefObjectId>
class SturdyRefRestorer;
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
template <typename VatId>
class BootstrapFactory: public _::BootstrapFactoryBase {
  // Interface that constructs per-client bootstrap interfaces. Use this if you want each client
  // who connects to see a different bootstrap interface based on their (authenticated) VatId.
  // This allows an application to bootstrap off of the authentication performed at the VatNetwork
  // level. (Typically VatId is some sort of public key.)
  //
  // This is only useful for multi-party networks. For TwoPartyVatNetwork, there's no reason to
  // use a BootstrapFactory; just specify a single bootstrap capability in this case.

public:
  virtual Capability::Client createFor(typename VatId::Reader clientId) = 0;
  // Create a bootstrap capability appropriate for exposing to the given client. VatNetwork will
  // have authenticated the client VatId before this is called.

private:
  Capability::Client baseCreateFor(AnyStruct::Reader clientId) override;
};

58
template <typename VatId>
59 60 61 62 63 64 65 66 67 68 69 70 71
class RpcSystem: public _::RpcSystemBase {
  // Represents the RPC system, which is the portal to objects available on the network.
  //
  // The RPC implementation sits on top of an implementation of `VatNetwork`.  The `VatNetwork`
  // determines how to form connections between vats -- specifically, two-way, private, reliable,
  // sequenced datagram connections.  The RPC implementation determines how to use such connections
  // to manage object references and make method calls.
  //
  // See `makeRpcServer()` and `makeRpcClient()` below for convenient syntax for setting up an
  // `RpcSystem` given a `VatNetwork`.
  //
  // See `ez-rpc.h` for an even simpler interface for setting up RPC in a typical two-party
  // client/server scenario.
72 73

public:
74 75 76 77
  template <typename ProvisionId, typename RecipientId,
            typename ThirdPartyCapId, typename JoinResult>
  RpcSystem(
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
78 79
      kj::Maybe<Capability::Client> bootstrapInterface,
      kj::Maybe<RealmGateway<>::Client> gateway = nullptr);
80

81 82 83 84 85 86 87
  template <typename ProvisionId, typename RecipientId,
            typename ThirdPartyCapId, typename JoinResult>
  RpcSystem(
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
      BootstrapFactory<VatId>& bootstrapFactory,
      kj::Maybe<RealmGateway<>::Client> gateway = nullptr);

88 89 90 91
  template <typename ProvisionId, typename RecipientId,
            typename ThirdPartyCapId, typename JoinResult,
            typename LocalSturdyRefObjectId>
  RpcSystem(
92 93 94
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
      SturdyRefRestorer<LocalSturdyRefObjectId>& restorer);

95
  RpcSystem(RpcSystem&& other) = default;
96

97 98 99 100
  Capability::Client bootstrap(typename VatId::Reader vatId);
  // Connect to the given vat and return its bootstrap interface.

  Capability::Client restore(typename VatId::Reader hostId, AnyPointer::Reader objectId)
101
      CAPNP_DEPRECATED("Please transition to using a bootstrap interface instead.");
102 103 104
  // ** DEPRECATED **
  //
  // Restores the given SturdyRef from the network and return the capability representing it.
105 106 107
  //
  // `hostId` identifies the host from which to request the ref, in the format specified by the
  // `VatNetwork` in use.  `objectId` is the object ID in whatever format is expected by said host.
108 109 110 111 112
  //
  // This method will be removed in a future version of Cap'n Proto. Instead, please transition
  // to using bootstrap(), which is equivalent to calling restore() with a null `objectId`.
  // You may emulate the old concept of object IDs by exporting a bootstrap interface which has
  // methods that can be used to obtain other capabilities by ID.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

  void setFlowLimit(size_t words);
  // Sets the incoming call flow limit. If more than `words` worth of call messages have not yet
  // received responses, the RpcSystem will not read further messages from the stream. This can be
  // used as a crude way to prevent a resource exhaustion attack (or bug) in which a peer makes an
  // excessive number of simultaneous calls that consume the receiver's RAM.
  //
  // There are some caveats. When over the flow limit, all messages are blocked, including returns.
  // If the outstanding calls are themselves waiting on calls going in the opposite direction, the
  // flow limit may prevent those calls from completing, leading to deadlock. However, a
  // sufficiently high limit should make this unlikely.
  //
  // Note that a call's parameter size counts against the flow limit until the call returns, even
  // if the recipient calls releaseParams() to free the parameter memory early. This is because
  // releaseParams() may simply indicate that the parameters have been forwarded to another
  // machine, but are still in-memory there. For illustration, say that Alice made a call to Bob
  // who forwarded the call to Carol. Bob has imposed a flow limit on Alice. Alice's calls are
  // being forwarded to Carol, so Bob never keeps the parameters in-memory for more than a brief
  // period. However, the flow limit counts all calls that haven't returned, even if Bob has
  // already freed the memory they consumed. You might argue that the right solution here is
  // instead for Carol to impose her own flow limit on Bob. This has a serious problem, though:
  // Bob might be forwarding requests to Carol on behalf of many different parties, not just Alice.
  // If Alice can pump enough data to hit the Bob -> Carol flow limit, then those other parties
  // will be disrupted. Thus, we can only really impose the limit on the Alice -> Bob link, which
  // only affects Alice. We need that one flow limit to limit Alice's impact on the whole system,
  // so it has to count all in-flight calls.
  //
  // In Sandstorm, flow limits are imposed by the supervisor on calls coming out of a grain, in
David Renshaw's avatar
David Renshaw committed
141
  // order to prevent a grain from inundating the system with in-flight calls. In practice, the
142 143
  // main time this happens is when a grain is pushing a large file download and doesn't implement
  // proper cooperative flow control.
144 145
};

146 147 148 149 150
template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    Capability::Client bootstrapInterface);
151 152 153
// Make an RPC server.  Typical usage (e.g. in a main() function):
//
//    MyEventLoop eventLoop;
154
//    kj::WaitScope waitScope(eventLoop);
155
//    MyNetwork network;
156 157
//    MyMainInterface::Client bootstrap = makeMain();
//    auto server = makeRpcServer(network, bootstrap);
158
//    kj::NEVER_DONE.wait(waitScope);  // run forever
159 160 161
//
// See also ez-rpc.h, which has simpler instructions for the common case of a two-party
// client-server RPC connection.
162

163
template <typename VatId, typename ProvisionId, typename RecipientId,
164 165 166
          typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
          typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
          typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
167 168
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
169 170 171 172 173 174 175 176 177 178 179 180
    Capability::Client bootstrapInterface, RealmGatewayClient gateway)
    CAPNP_DEPRECATED("Please transition to using MembranePolicy instead of RealmGateway.");
// ** DEPRECATED **
//
// This uses a RealmGateway to create a membrane between the external network and internal
// capabilites to translate save() requests. However, MembranePolicy (membrane.h) allows for the
// creation of much more powerful membranes and doesn't need to be tied to an RpcSystem.
// Applications should transition to using membranes instead of RealmGateway. RealmGateway will be
// removed in a future version of Cap'n Proto.
//
// Original description:
//
181 182 183 184
// Make an RPC server for a VatNetwork that resides in a different realm from the application.
// The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
// and the network's ("external") format.

185 186 187 188 189 190 191 192 193 194 195 196 197 198
template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    BootstrapFactory<VatId>& bootstrapFactory);
// Make an RPC server that can serve different bootstrap interfaces to different clients via a
// BootstrapInterface.

template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
          typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
          typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
199 200 201 202 203 204 205 206 207 208 209 210
    BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway)
    CAPNP_DEPRECATED("Please transition to using MembranePolicy instead of RealmGateway.");
// ** DEPRECATED **
//
// This uses a RealmGateway to create a membrane between the external network and internal
// capabilites to translate save() requests. However, MembranePolicy (membrane.h) allows for the
// creation of much more powerful membranes and doesn't need to be tied to an RpcSystem.
// Applications should transition to using membranes instead of RealmGateway. RealmGateway will be
// removed in a future version of Cap'n Proto.
//
// Original description:
//
211 212 213 214
// Make an RPC server that can serve different bootstrap interfaces to different clients via a
// BootstrapInterface and communicates with a different realm than the application is in via a
// RealmGateway.

215 216 217 218 219
template <typename VatId, typename LocalSturdyRefObjectId,
          typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
220
    CAPNP_DEPRECATED("Please transition to using a bootstrap interface instead.");
221 222 223 224 225 226 227 228 229 230 231 232 233
// ** DEPRECATED **
//
// Create an RPC server which exports multiple main interfaces by object ID. The `restorer` object
// can be used to look up objects by ID.
//
// Please transition to exporting only one interface, which is known as the "bootstrap" interface.
// For backwards-compatibility with old clients, continue to implement SturdyRefRestorer, but
// return the new bootstrap interface when the request object ID is null. When new clients connect
// and request the bootstrap interface, they will get that interface. Eventually, once all clients
// are updated to request only the bootstrap interface, stop implementing SturdyRefRestorer and
// switch to passing the bootstrap capability itself as the second parameter to `makeRpcServer()`.

template <typename VatId, typename ProvisionId,
234
          typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
235 236
RpcSystem<VatId> makeRpcClient(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network);
237 238 239
// Make an RPC client.  Typical usage (e.g. in a main() function):
//
//    MyEventLoop eventLoop;
240
//    kj::WaitScope waitScope(eventLoop);
241
//    MyNetwork network;
242
//    auto client = makeRpcClient(network);
243
//    MyCapability::Client cap = client.restore(hostId, objId).castAs<MyCapability>();
244
//    auto response = cap.fooRequest().send().wait(waitScope);
245 246 247 248
//    handleMyResponse(response);
//
// See also ez-rpc.h, which has simpler instructions for the common case of a two-party
// client-server RPC connection.
249

250
template <typename VatId, typename ProvisionId, typename RecipientId,
251 252 253
          typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
          typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
          typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
254 255
RpcSystem<VatId> makeRpcClient(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
256 257 258 259 260 261 262 263 264 265 266 267
    RealmGatewayClient gateway)
    CAPNP_DEPRECATED("Please transition to using MembranePolicy instead of RealmGateway.");
// ** DEPRECATED **
//
// This uses a RealmGateway to create a membrane between the external network and internal
// capabilites to translate save() requests. However, MembranePolicy (membrane.h) allows for the
// creation of much more powerful membranes and doesn't need to be tied to an RpcSystem.
// Applications should transition to using membranes instead of RealmGateway. RealmGateway will be
// removed in a future version of Cap'n Proto.
//
// Original description:
//
268 269 270 271
// Make an RPC client for a VatNetwork that resides in a different realm from the application.
// The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
// and the network's ("external") format.

272 273
template <typename SturdyRefObjectId>
class SturdyRefRestorer: public _::SturdyRefRestorerBase {
274 275 276 277 278 279 280 281 282 283
  // ** DEPRECATED **
  //
  // In Cap'n Proto 0.4.x, applications could export multiple main interfaces identified by
  // object IDs. The callback used to map object IDs to objects was `SturdyRefRestorer`, as we
  // imagined this would eventually be used for restoring SturdyRefs as well. In practice, it was
  // never used for real SturdyRefs, only for exporting singleton objects under well-known names.
  //
  // The new preferred strategy is to export only a _single_ such interface, called the
  // "bootstrap interface". That interface can itself have methods for obtaining other objects, of
  // course, but that is up to the app. `SturdyRefRestorer` exists for backwards-compatibility.
284 285 286
  //
  // Hint:  Use SturdyRefRestorer<capnp::Text> to define a server that exports services under
  //   string names.
287

288
public:
289 290
  virtual Capability::Client restore(typename SturdyRefObjectId::Reader ref) CAPNP_DEPRECATED(
      "Please transition to using bootstrap interfaces instead of SturdyRefRestorer.") = 0;
291
  // Restore the given object, returning a capability representing it.
292

293
private:
294
  Capability::Client baseRestore(AnyPointer::Reader ref) override final;
295 296 297
};

// =======================================================================================
298
// VatNetwork
299 300

class OutgoingRpcMessage {
301 302
  // A message to be sent by a `VatNetwork`.

303
public:
304
  virtual AnyPointer::Builder getBody() = 0;
305 306 307 308 309 310 311 312 313
  // Get the message body, which the caller may fill in any way it wants.  (The standard RPC
  // implementation initializes it as a Message as defined in rpc.capnp.)

  virtual void send() = 0;
  // Send the message, or at least put it in a queue to be sent later.  Note that the builder
  // returned by `getBody()` remains valid at least until the `OutgoingRpcMessage` is destroyed.
};

class IncomingRpcMessage {
314 315
  // A message received from a `VatNetwork`.

316
public:
317
  virtual AnyPointer::Reader getBody() = 0;
318 319 320 321
  // Get the message body, to be interpreted by the caller.  (The standard RPC implementation
  // interprets it as a Message as defined in rpc.capnp.)
};

322
template <typename VatId, typename ProvisionId, typename RecipientId,
323
          typename ThirdPartyCapId, typename JoinResult>
324
class VatNetwork: public _::VatNetworkBase {
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
  // Cap'n Proto RPC operates between vats, where a "vat" is some sort of host of objects.
  // Typically one Cap'n Proto process (in the Unix sense) is one vat.  The RPC system is what
  // allows calls between objects hosted in different vats.
  //
  // The RPC implementation sits on top of an implementation of `VatNetwork`.  The `VatNetwork`
  // determines how to form connections between vats -- specifically, two-way, private, reliable,
  // sequenced datagram connections.  The RPC implementation determines how to use such connections
  // to manage object references and make method calls.
  //
  // The most common implementation of VatNetwork is TwoPartyVatNetwork (rpc-twoparty.h).  Most
  // simple client-server apps will want to use it.  (You may even want to use the EZ RPC
  // interfaces in `ez-rpc.h` and avoid all of this.)
  //
  // TODO(someday):  Provide a standard implementation for the public internet.

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
public:
  class Connection;

  struct ConnectionAndProvisionId {
    // Result of connecting to a vat introduced by another vat.

    kj::Own<Connection> connection;
    // Connection to the new vat.

    kj::Own<OutgoingRpcMessage> firstMessage;
    // An already-allocated `OutgoingRpcMessage` associated with `connection`.  The RPC system will
    // construct this as an `Accept` message and send it.

    Orphan<ProvisionId> provisionId;
    // A `ProvisionId` already allocated inside `firstMessage`, which the RPC system will use to
    // build the `Accept` message.
  };

  class Connection: public _::VatNetworkBase::Connection {
    // A two-way RPC connection.
    //
    // This object may represent a connection that doesn't exist yet, but is expected to exist
    // in the future.  In this case, sent messages will automatically be queued and sent once the
    // connection is ready, so that the caller doesn't need to know the difference.

  public:
    // Level 0 features ----------------------------------------------

368 369 370 371 372
    virtual typename VatId::Reader getPeerVatId() = 0;
    // Returns the connected vat's authenticated VatId. It is the VatNetwork's responsibility to
    // authenticate this, so that the caller can be assured that they are really talking to the
    // identified vat and not an imposter.

373
    virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override = 0;
374 375 376 377 378 379
    // Allocate a new message to be sent on this connection.
    //
    // If `firstSegmentWordSize` is non-zero, it should be treated as a hint suggesting how large
    // to make the first segment.  This is entirely a hint and the connection may adjust it up or
    // down.  If it is zero, the connection should choose the size itself.

380
    virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override = 0;
381 382
    // Wait for a message to be received and return it.  If the read stream cleanly terminates,
    // return null.  If any other problem occurs, throw an exception.
Kenton Varda's avatar
Kenton Varda committed
383

384
    virtual kj::Promise<void> shutdown() override KJ_WARN_UNUSED_RESULT = 0;
Kenton Varda's avatar
Kenton Varda committed
385 386
    // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
    // returned promise resolves after shutdown is complete.
387 388 389

  private:
    AnyStruct::Reader baseGetPeerVatId() override;
390 391 392 393
  };

  // Level 0 features ------------------------------------------------

394 395
  virtual kj::Maybe<kj::Own<Connection>> connect(typename VatId::Reader hostId) = 0;
  // Connect to a VatId.  Note that this method immediately returns a `Connection`, even
396 397 398 399 400 401 402
  // if the network connection has not yet been established.  Messages can be queued to this
  // connection and will be delivered once it is open.  The caller must attempt to read from the
  // connection to verify that it actually succeeded; the read will fail if the connection
  // couldn't be opened.  Some network implementations may actually start sending messages before
  // hearing back from the server at all, to avoid a round trip.
  //
  // Returns nullptr if `hostId` refers to the local host.
403

404 405
  virtual kj::Promise<kj::Own<Connection>> accept() = 0;
  // Wait for the next incoming connection and return it.
406 407 408 409 410

  // Level 4 features ------------------------------------------------
  // TODO(someday)

private:
411
  kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
412
      baseConnect(AnyStruct::Reader hostId) override final;
413
  kj::Promise<kj::Own<_::VatNetworkBase::Connection>> baseAccept() override final;
414 415 416 417 418 419 420 421
};

// =======================================================================================
// ***************************************************************************************
// Inline implementation details start here
// ***************************************************************************************
// =======================================================================================

422 423 424 425 426
template <typename VatId>
Capability::Client BootstrapFactory<VatId>::baseCreateFor(AnyStruct::Reader clientId) {
  return createFor(clientId.as<VatId>());
}

427
template <typename SturdyRef, typename ProvisionId, typename RecipientId,
428
          typename ThirdPartyCapId, typename JoinResult>
429
kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
430
    VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
431 432
    baseConnect(AnyStruct::Reader ref) {
  auto maybe = connect(ref.as<SturdyRef>());
433 434 435
  return maybe.map([](kj::Own<Connection>& conn) -> kj::Own<_::VatNetworkBase::Connection> {
    return kj::mv(conn);
  });
436 437 438
}

template <typename SturdyRef, typename ProvisionId, typename RecipientId,
439
          typename ThirdPartyCapId, typename JoinResult>
440
kj::Promise<kj::Own<_::VatNetworkBase::Connection>>
441 442
    VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::baseAccept() {
  return accept().then(
443 444 445 446 447
      [](kj::Own<Connection>&& connection) -> kj::Own<_::VatNetworkBase::Connection> {
    return kj::mv(connection);
  });
}

448 449 450 451 452 453 454 455
template <typename SturdyRef, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
AnyStruct::Reader VatNetwork<
    SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
    Connection::baseGetPeerVatId() {
  return getPeerVatId();
}

456
template <typename SturdyRef>
457
Capability::Client SturdyRefRestorer<SturdyRef>::baseRestore(AnyPointer::Reader ref) {
458 459
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
460
  return restore(ref.getAs<SturdyRef>());
461
#pragma GCC diagnostic pop
462 463
}

464 465 466 467 468
template <typename VatId>
template <typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId>::RpcSystem(
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
469 470 471
      kj::Maybe<Capability::Client> bootstrap,
      kj::Maybe<RealmGateway<>::Client> gateway)
    : _::RpcSystemBase(network, kj::mv(bootstrap), kj::mv(gateway)) {}
472

473 474 475 476 477 478 479 480 481
template <typename VatId>
template <typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId>::RpcSystem(
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
      BootstrapFactory<VatId>& bootstrapFactory,
      kj::Maybe<RealmGateway<>::Client> gateway)
    : _::RpcSystemBase(network, bootstrapFactory, kj::mv(gateway)) {}

482
template <typename VatId>
483
template <typename ProvisionId, typename RecipientId,
484
          typename ThirdPartyCapId, typename JoinResult,
485
          typename LocalSturdyRefObjectId>
486 487 488
RpcSystem<VatId>::RpcSystem(
      VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
      SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
489
    : _::RpcSystemBase(network, restorer) {}
490

491 492 493 494 495 496 497 498 499 500 501
template <typename VatId>
Capability::Client RpcSystem<VatId>::bootstrap(typename VatId::Reader vatId) {
  return baseBootstrap(_::PointerHelpers<VatId>::getInternalReader(vatId));
}

template <typename VatId>
Capability::Client RpcSystem<VatId>::restore(
    typename VatId::Reader hostId, AnyPointer::Reader objectId) {
  return baseRestore(_::PointerHelpers<VatId>::getInternalReader(hostId), objectId);
}

502 503 504 505 506
template <typename VatId>
inline void RpcSystem<VatId>::setFlowLimit(size_t words) {
  baseSetFlowLimit(words);
}

507 508 509 510 511 512
template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    Capability::Client bootstrapInterface) {
  return RpcSystem<VatId>(network, kj::mv(bootstrapInterface));
513 514
}

515 516
template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult,
517
          typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
518 519
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
520
    Capability::Client bootstrapInterface, RealmGatewayClient gateway) {
521 522 523 524
  return RpcSystem<VatId>(network, kj::mv(bootstrapInterface),
      gateway.template castAs<RealmGateway<>>());
}

525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    BootstrapFactory<VatId>& bootstrapFactory) {
  return RpcSystem<VatId>(network, bootstrapFactory);
}

template <typename VatId, typename ProvisionId, typename RecipientId,
          typename ThirdPartyCapId, typename JoinResult,
          typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
    BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway) {
  return RpcSystem<VatId>(network, bootstrapFactory, gateway.template castAs<RealmGateway<>>());
}

542
template <typename VatId, typename LocalSturdyRefObjectId,
543
          typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
544 545
RpcSystem<VatId> makeRpcServer(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
546
    SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) {
547
  return RpcSystem<VatId>(network, restorer);
548 549
}

550
template <typename VatId, typename ProvisionId,
551
          typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
552 553 554
RpcSystem<VatId> makeRpcClient(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network) {
  return RpcSystem<VatId>(network, nullptr);
555 556
}

557 558
template <typename VatId, typename ProvisionId,
          typename RecipientId, typename ThirdPartyCapId, typename JoinResult,
559
          typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
560 561
RpcSystem<VatId> makeRpcClient(
    VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
562
    RealmGatewayClient gateway) {
563 564 565
  return RpcSystem<VatId>(network, nullptr, gateway.template castAs<RealmGateway<>>());
}

566
}  // namespace capnp