Commit 9a32fa73 authored by Kenton Varda's avatar Kenton Varda

RPC: Rename 'Restore' to 'Bootstrap' and redefine it to have nothing to do with SturdyRefs.

The 'objectId' field is now deprecated. Long-term, each vat will export no more than one "bootstrap interface" which can be obtained via 'Bootstrap'. Restoring SturdyRefs will be accomplished through higher-level interfaces specific to the VatNetwork in use.

See comments for 'Bootstrap' in rpc.capnp for more discussion.
parent 46c48dfe
......@@ -48,7 +48,7 @@ int main(int argc, const char* argv[]) {
}
capnp::EzRpcClient client(argv[1]);
Calculator::Client calculator = client.importCap<Calculator>("calculator");
Calculator::Client calculator = client.getMain<Calculator>();
// Keep an eye on `waitScope`. Whenever you see it used is a place where we
// stop and wait for the server to respond. If a line of code does not use
......
......@@ -197,8 +197,7 @@ int main(int argc, const char* argv[]) {
}
// Set up a server.
capnp::EzRpcServer server(argv[1]);
server.exportCap("calculator", kj::heap<CalculatorImpl>());
capnp::EzRpcServer server(kj::heap<CalculatorImpl>(), argv[1]);
// Write the port number to stdout, in case it was chosen automatically.
auto& waitScope = server.getWaitScope();
......
......@@ -28,6 +28,23 @@ namespace _ {
namespace {
TEST(EzRpc, Basic) {
int callCount = 0;
EzRpcServer server(kj::heap<TestInterfaceImpl>(callCount), "localhost");
EzRpcClient client("localhost", server.getPort().wait(server.getWaitScope()));
auto cap = client.getMain<test::TestInterface>();
auto request = cap.fooRequest();
request.setI(123);
request.setJ(true);
EXPECT_EQ(0, callCount);
auto response = request.send().wait(server.getWaitScope());
EXPECT_EQ("foo", response.getX());
EXPECT_EQ(1, callCount);
}
TEST(EzRpc, DeprecatedNames) {
EzRpcServer server("localhost");
int callCount = 0;
server.exportCap("cap1", kj::heap<TestInterfaceImpl>(callCount));
......
......@@ -78,22 +78,37 @@ struct EzRpcClient::Impl {
struct ClientContext {
kj::Own<kj::AsyncIoStream> stream;
TwoPartyVatNetwork network;
RpcSystem<rpc::twoparty::SturdyRefHostId> rpcSystem;
RpcSystem<rpc::twoparty::VatId> rpcSystem;
ClientContext(kj::Own<kj::AsyncIoStream>&& stream, ReaderOptions readerOpts)
: stream(kj::mv(stream)),
network(*this->stream, rpc::twoparty::Side::CLIENT, readerOpts),
rpcSystem(makeRpcClient(network)) {}
Capability::Client getMain() {
word scratch[4];
memset(scratch, 0, sizeof(scratch));
MallocMessageBuilder message(scratch);
auto hostId = message.getRoot<rpc::twoparty::VatId>();
hostId.setSide(rpc::twoparty::Side::SERVER);
return rpcSystem.bootstrap(hostId);
}
Capability::Client restore(kj::StringPtr name) {
word scratch[64];
memset(scratch, 0, sizeof(scratch));
MallocMessageBuilder message(scratch);
auto root = message.getRoot<rpc::SturdyRef>();
auto hostId = root.getHostId().getAs<rpc::twoparty::SturdyRefHostId>();
auto hostIdOrphan = message.getOrphanage().newOrphan<rpc::twoparty::VatId>();
auto hostId = hostIdOrphan.get();
hostId.setSide(rpc::twoparty::Side::SERVER);
root.getObjectId().setAs<Text>(name);
return rpcSystem.restore(hostId, root.getObjectId());
auto objectId = message.getRoot<AnyPointer>();
objectId.setAs<Text>(name);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return rpcSystem.restore(hostId, objectId);
#pragma GCC diagnostic pop
}
};
......@@ -143,6 +158,16 @@ EzRpcClient::EzRpcClient(int socketFd, ReaderOptions readerOpts)
EzRpcClient::~EzRpcClient() noexcept(false) {}
Capability::Client EzRpcClient::getMain() {
KJ_IF_MAYBE(client, impl->clientContext) {
return client->get()->getMain();
} else {
return impl->setupPromise.addBranch().then([this]() {
return KJ_ASSERT_NONNULL(impl->clientContext)->getMain();
});
}
}
Capability::Client EzRpcClient::importCap(kj::StringPtr name) {
KJ_IF_MAYBE(client, impl->clientContext) {
return client->get()->restore(name);
......@@ -168,7 +193,9 @@ kj::LowLevelAsyncIoProvider& EzRpcClient::getLowLevelIoProvider() {
// =======================================================================================
struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskSet::ErrorHandler {
struct EzRpcServer::Impl final: public SturdyRefRestorer<AnyPointer>,
public kj::TaskSet::ErrorHandler {
Capability::Client mainInterface;
kj::Own<EzRpcContext> context;
struct ExportedCap {
......@@ -195,17 +222,22 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
struct ServerContext {
kj::Own<kj::AsyncIoStream> stream;
TwoPartyVatNetwork network;
RpcSystem<rpc::twoparty::SturdyRefHostId> rpcSystem;
RpcSystem<rpc::twoparty::VatId> rpcSystem;
ServerContext(kj::Own<kj::AsyncIoStream>&& stream, SturdyRefRestorer<Text>& restorer,
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
ServerContext(kj::Own<kj::AsyncIoStream>&& stream, SturdyRefRestorer<AnyPointer>& restorer,
ReaderOptions readerOpts)
: stream(kj::mv(stream)),
network(*this->stream, rpc::twoparty::Side::SERVER, readerOpts),
rpcSystem(makeRpcServer(network, restorer)) {}
#pragma GCC diagnostic pop
};
Impl(kj::StringPtr bindAddress, uint defaultPort, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) {
Impl(Capability::Client mainInterface, kj::StringPtr bindAddress, uint defaultPort,
ReaderOptions readerOpts)
: mainInterface(kj::mv(mainInterface)),
context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) {
auto paf = kj::newPromiseAndFulfiller<uint>();
portPromise = paf.promise.fork();
......@@ -219,16 +251,19 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
})));
}
Impl(struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) {
Impl(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize,
ReaderOptions readerOpts)
: mainInterface(kj::mv(mainInterface)),
context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) {
auto listener = context->getIoProvider().getNetwork()
.getSockaddr(bindAddress, addrSize)->listen();
portPromise = kj::Promise<uint>(listener->getPort()).fork();
acceptLoop(kj::mv(listener), readerOpts);
}
Impl(int socketFd, uint port, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()),
Impl(Capability::Client mainInterface, int socketFd, uint port, ReaderOptions readerOpts)
: mainInterface(kj::mv(mainInterface)),
context(EzRpcContext::getThreadLocal()),
portPromise(kj::Promise<uint>(port).fork()),
tasks(*this) {
acceptLoop(context->getLowLevelIoProvider().wrapListenSocketFd(socketFd), readerOpts);
......@@ -249,13 +284,18 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
})));
}
Capability::Client restore(Text::Reader name) override {
auto iter = exportMap.find(name);
if (iter == exportMap.end()) {
KJ_FAIL_REQUIRE("Server exports no such capability.", name) { break; }
return nullptr;
Capability::Client restore(AnyPointer::Reader objectId) override {
if (objectId.isNull()) {
return mainInterface;
} else {
return iter->second.cap;
auto name = objectId.getAs<Text>();
auto iter = exportMap.find(name);
if (iter == exportMap.end()) {
KJ_FAIL_REQUIRE("Server exports no such capability.", name) { break; }
return nullptr;
} else {
return iter->second.cap;
}
}
}
......@@ -264,16 +304,28 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
}
};
EzRpcServer::EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress,
uint defaultPort, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(kj::mv(mainInterface), bindAddress, defaultPort, readerOpts)) {}
EzRpcServer::EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress,
uint addrSize, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(kj::mv(mainInterface), bindAddress, addrSize, readerOpts)) {}
EzRpcServer::EzRpcServer(Capability::Client mainInterface, int socketFd, uint port,
ReaderOptions readerOpts)
: impl(kj::heap<Impl>(kj::mv(mainInterface), socketFd, port, readerOpts)) {}
EzRpcServer::EzRpcServer(kj::StringPtr bindAddress, uint defaultPort,
ReaderOptions readerOpts)
: impl(kj::heap<Impl>(bindAddress, defaultPort, readerOpts)) {}
: EzRpcServer(nullptr, bindAddress, defaultPort, readerOpts) {}
EzRpcServer::EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
ReaderOptions readerOpts)
: impl(kj::heap<Impl>(bindAddress, addrSize, readerOpts)) {}
: EzRpcServer(nullptr, bindAddress, addrSize, readerOpts) {}
EzRpcServer::EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(socketFd, port, readerOpts)) {}
: EzRpcServer(nullptr, socketFd, port, readerOpts) {}
EzRpcServer::~EzRpcServer() noexcept(false) {}
......
......@@ -44,7 +44,7 @@ class EzRpcClient {
// // C++ client
// int main() {
// capnp::EzRpcClient client("localhost:3456");
// Adder::Client adder = client.importCap<Adder>("adder");
// Adder::Client adder = client.getMain<Adder>();
// auto request = adder.addRequest();
// request.setLeft(12);
// request.setRight(34);
......@@ -64,8 +64,7 @@ class EzRpcClient {
// };
//
// int main() {
// capnp::EzRpcServer server("*:3456");
// server.exportCap("adder", kj::heap<AdderImpl>());
// capnp::EzRpcServer server(kj::heap<AdderImpl>(), "*:3456");
// kj::NEVER_DONE.wait(server.getWaitScope());
// }
//
......@@ -110,11 +109,6 @@ public:
// your protocol to send large data blobs in multiple small chunks -- this is much better for
// both security and performance. See `ReaderOptions` in `message.h` for more details.
// You should only need to set this if you are receiving errors about messages being too large or
// too deep in normal operation, and should consider restructuring your protocol to use simpler
// or smaller messages if this is an issue for you.
EzRpcClient(const struct sockaddr* serverAddress, uint addrSize,
ReaderOptions readerOpts = ReaderOptions());
// Like the above constructor, but connects to an already-resolved socket address. Any address
......@@ -127,10 +121,22 @@ public:
~EzRpcClient() noexcept(false);
template <typename Type>
typename Type::Client importCap(kj::StringPtr name);
Capability::Client importCap(kj::StringPtr name);
typename Type::Client getMain();
Capability::Client getMain();
// Get the server's main (aka "bootstrap") interface.
template <typename Type>
typename Type::Client importCap(kj::StringPtr name)
KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
Capability::Client importCap(kj::StringPtr name)
KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
// ** DEPRECATED **
//
// Ask the sever for the capability with the given name. You may specify a type to automatically
// down-cast to that type. It is up to you to specify the correct expected type.
//
// Named interfaces are deprecated. The new preferred usage pattern is for the server to export
// a "main" interface which itself has methods for getting any other interfaces.
kj::WaitScope& getWaitScope();
// Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
......@@ -153,8 +159,8 @@ class EzRpcServer {
// The server counterpart to `EzRpcClient`. See `EzRpcClient` for an example.
public:
explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0,
ReaderOptions readerOpts = ReaderOptions());
explicit EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress,
uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions());
// Construct a new `EzRpcServer` that binds to the given address. An address of "*" means to
// bind to all local addresses.
//
......@@ -175,16 +181,26 @@ public:
// your protocol to send large data blobs in multiple small chunks -- this is much better for
// both security and performance. See `ReaderOptions` in `message.h` for more details.
EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize,
ReaderOptions readerOpts = ReaderOptions());
// Like the above constructor, but binds to an already-resolved socket address. Any address
// format supported by `kj::Network` in `kj/async-io.h` is accepted.
EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions());
EzRpcServer(Capability::Client mainInterface, int socketFd, uint port,
ReaderOptions readerOpts = ReaderOptions());
// Create a server on top of an already-listening socket (i.e. one on which accept() may be
// called). `port` is returned by `getPort()` -- it serves no other purpose.
// `readerOpts` acts as in the other two above constructors.
explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0,
ReaderOptions readerOpts = ReaderOptions())
KJ_DEPRECATED("Please specify a main interface for your server.");
EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
ReaderOptions readerOpts = ReaderOptions())
KJ_DEPRECATED("Please specify a main interface for your server.");
EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions())
KJ_DEPRECATED("Please specify a main interface for your server.");
~EzRpcServer() noexcept(false);
void exportCap(kj::StringPtr name, Capability::Client cap);
......@@ -219,6 +235,11 @@ private:
// =======================================================================================
// inline implementation details
template <typename Type>
inline typename Type::Client EzRpcClient::getMain() {
return getMain().castAs<Type>();
}
template <typename Type>
inline typename Type::Client EzRpcClient::importCap(kj::StringPtr name) {
return importCap(name).castAs<Type>();
......
......@@ -2156,11 +2156,21 @@ bool PointerBuilder::isNull() {
}
void PointerBuilder::transferFrom(PointerBuilder other) {
if (!pointer->isNull()) {
WireHelpers::zeroObject(segment, pointer);
memset(pointer, 0, sizeof(*pointer));
}
WireHelpers::transferPointer(segment, pointer, other.segment, other.pointer);
}
void PointerBuilder::copyFrom(PointerReader other) {
WireHelpers::copyPointer(segment, pointer, other.segment, other.pointer, other.nestingLimit);
if (!pointer->isNull()) {
WireHelpers::zeroObject(segment, pointer);
memset(pointer, 0, sizeof(*pointer));
}
if (other.pointer != nullptr) {
WireHelpers::copyPointer(segment, pointer, other.segment, other.pointer, other.nestingLimit);
}
}
PointerReader PointerBuilder::asReader() const {
......@@ -2220,7 +2230,8 @@ const word* PointerReader::getUnchecked() const {
}
MessageSizeCounts PointerReader::targetSize() const {
return WireHelpers::totalSize(segment, pointer, nestingLimit);
return pointer == nullptr ? MessageSizeCounts { 0 * WORDS, 0 }
: WireHelpers::totalSize(segment, pointer, nestingLimit);
}
bool PointerReader::isNull() const {
......
......@@ -53,13 +53,9 @@ public:
public:
virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) = 0;
virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() = 0;
virtual void baseIntroduceTo(Connection& recipient,
AnyPointer::Builder sendToRecipient, AnyPointer::Builder sendToTarget) = 0;
virtual ConnectionAndProvisionId baseConnectToIntroduced(AnyPointer::Reader capId) = 0;
virtual kj::Own<Connection> baseAcceptIntroducedConnection(AnyPointer::Reader recipientId) = 0;
};
virtual kj::Maybe<kj::Own<Connection>> baseConnectToRefHost(_::StructReader hostId) = 0;
virtual kj::Promise<kj::Own<Connection>> baseAcceptConnectionAsRefHost() = 0;
virtual kj::Maybe<kj::Own<Connection>> baseConnect(_::StructReader vatId) = 0;
virtual kj::Promise<kj::Own<Connection>> baseAccept() = 0;
};
class SturdyRefRestorerBase {
......@@ -69,7 +65,8 @@ public:
class RpcSystemBase {
public:
RpcSystemBase(VatNetworkBase& network, kj::Maybe<SturdyRefRestorerBase&> restorer);
RpcSystemBase(VatNetworkBase& network, kj::Maybe<Capability::Client> bootstrapInterface);
RpcSystemBase(VatNetworkBase& network, SturdyRefRestorerBase& restorer);
RpcSystemBase(RpcSystemBase&& other) noexcept;
~RpcSystemBase() noexcept(false);
......@@ -77,7 +74,8 @@ private:
class Impl;
kj::Own<Impl> impl;
Capability::Client baseRestore(_::StructReader hostId, AnyPointer::Reader objectId);
Capability::Client baseBootstrap(_::StructReader vatId);
Capability::Client baseRestore(_::StructReader vatId, AnyPointer::Reader objectId);
// TODO(someday): Maybe define a public API called `TypelessStruct` so we don't have to rely
// on `_::StructReader` here?
......
......@@ -73,8 +73,8 @@ public:
schemaProto.getDisplayName().slice(schemaProto.getDisplayNamePrefixLength());
auto methodProto = method.getProto();
auto paramType = schema.getDependency(methodProto.getParamStructType()).asStruct();
auto resultType = schema.getDependency(methodProto.getResultStructType()).asStruct();
auto paramType = method.getParamType();
auto resultType = method.getResultType();
if (call.getSendResultsTo().isCaller()) {
returnTypes[std::make_pair(sender, call.getQuestionId())] = resultType;
......@@ -126,13 +126,13 @@ public:
}
}
case rpc::Message::RESTORE: {
auto restore = message.getRestore();
case rpc::Message::BOOTSTRAP: {
auto restore = message.getBootstrap();
returnTypes[std::make_pair(sender, restore.getQuestionId())] = InterfaceSchema();
return kj::str(senderName, "(", restore.getQuestionId(), "): restore ",
restore.getObjectId().getAs<test::TestSturdyRefObjectId>());
return kj::str(senderName, "(", restore.getQuestionId(), "): bootstrap ",
restore.getDeprecatedObjectId().getAs<test::TestSturdyRefObjectId>());
}
default:
......@@ -314,19 +314,6 @@ public:
return kj::Maybe<kj::Own<IncomingRpcMessage>>(kj::mv(result));
}
}
void introduceTo(Connection& recipient,
test::TestThirdPartyCapId::Builder sendToRecipient,
test::TestRecipientId::Builder sendToTarget) override {
KJ_FAIL_ASSERT("not implemented");
}
ConnectionAndProvisionId connectToIntroduced(
test::TestThirdPartyCapId::Reader capId) override {
KJ_FAIL_ASSERT("not implemented");
}
kj::Own<Connection> acceptIntroducedConnection(
test::TestRecipientId::Reader recipientId) override {
KJ_FAIL_ASSERT("not implemented");
}
void taskFailed(kj::Exception&& exception) override {
ADD_FAILURE() << kj::str(exception).cStr();
......@@ -345,8 +332,7 @@ public:
kj::Own<kj::TaskSet> tasks;
};
kj::Maybe<kj::Own<Connection>> connectToRefHost(
test::TestSturdyRefHostId::Reader hostId) override {
kj::Maybe<kj::Own<Connection>> connect(test::TestSturdyRefHostId::Reader hostId) override {
TestNetworkAdapter& dst = KJ_REQUIRE_NONNULL(network.find(hostId.getHost()));
auto iter = connections.find(&dst);
......@@ -371,7 +357,7 @@ public:
}
}
kj::Promise<kj::Own<Connection>> acceptConnectionAsRefHost() override {
kj::Promise<kj::Own<Connection>> accept() override {
if (connectionQueue.empty()) {
auto paf = kj::newPromiseAndFulfiller<kj::Own<Connection>>();
fulfillerQueue.push(kj::mv(paf.fulfiller));
......@@ -444,8 +430,8 @@ struct TestContext {
Capability::Client connect(test::TestSturdyRefObjectId::Tag tag) {
MallocMessageBuilder refMessage(128);
auto ref = refMessage.initRoot<rpc::SturdyRef>();
auto hostId = ref.getHostId().initAs<test::TestSturdyRefHostId>();
auto ref = refMessage.initRoot<test::TestSturdyRef>();
auto hostId = ref.initHostId();
hostId.setHost("server");
ref.getObjectId().initAs<test::TestSturdyRefObjectId>().setTag(tag);
......
......@@ -70,12 +70,12 @@ kj::AsyncIoProvider::PipeThread runServer(kj::AsyncIoProvider& ioProvider,
});
}
Capability::Client getPersistentCap(RpcSystem<rpc::twoparty::SturdyRefHostId>& client,
Capability::Client getPersistentCap(RpcSystem<rpc::twoparty::VatId>& client,
rpc::twoparty::Side side,
test::TestSturdyRefObjectId::Tag tag) {
// Create the SturdyRefHostId.
// Create the VatId.
MallocMessageBuilder hostIdMessage(8);
auto hostId = hostIdMessage.initRoot<rpc::twoparty::SturdyRefHostId>();
auto hostId = hostIdMessage.initRoot<rpc::twoparty::VatId>();
hostId.setSide(side);
// Create the SturdyRefObjectId.
......
......@@ -44,8 +44,8 @@ kj::Own<TwoPartyVatNetworkBase::Connection> TwoPartyVatNetwork::asConnection() {
return kj::Own<TwoPartyVatNetworkBase::Connection>(this, disconnectFulfiller);
}
kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> TwoPartyVatNetwork::connectToRefHost(
rpc::twoparty::SturdyRefHostId::Reader ref) {
kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> TwoPartyVatNetwork::connect(
rpc::twoparty::VatId::Reader ref) {
if (ref.getSide() == side) {
return nullptr;
} else {
......@@ -53,8 +53,7 @@ kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> TwoPartyVatNetwork::conne
}
}
kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>>
TwoPartyVatNetwork::acceptConnectionAsRefHost() {
kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>> TwoPartyVatNetwork::accept() {
if (side == rpc::twoparty::Side::SERVER && !accepted) {
accepted = true;
return asConnection();
......@@ -133,20 +132,4 @@ kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> TwoPartyVatNetwork::receiveI
});
}
void TwoPartyVatNetwork::introduceTo(TwoPartyVatNetworkBase::Connection& recipient,
rpc::twoparty::ThirdPartyCapId::Builder sendToRecipient,
rpc::twoparty::RecipientId::Builder sendToTarget) {
KJ_FAIL_REQUIRE("Three-party introductions should never occur on two-party network.");
}
TwoPartyVatNetworkBase::ConnectionAndProvisionId TwoPartyVatNetwork::connectToIntroduced(
rpc::twoparty::ThirdPartyCapId::Reader capId) {
KJ_FAIL_REQUIRE("Three-party introductions should never occur on two-party network.");
}
kj::Own<TwoPartyVatNetworkBase::Connection> TwoPartyVatNetwork::acceptIntroducedConnection(
rpc::twoparty::RecipientId::Reader recipientId) {
KJ_FAIL_REQUIRE("Three-party introductions should never occur on two-party network.");
}
} // namespace capnp
......@@ -72,25 +72,28 @@
using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("capnp::rpc::twoparty");
# Note: SturdyRef is not specified here. It is up to the application to define semantics of
# SturdyRefs if desired.
enum Side {
server @0;
# The object lives on the "server" or "supervisor" end of the connection. Only the
# The object lives on the "server" or "supervisor" end of the connection. Only the
# server/supervisor knows how to interpret the ref; to the client, it is opaque.
#
# Note that containers intending to implement strong confinement should rewrite SturdyRefs
# received from the external network before passing them on to the confined app. The confined
# received from the external network before passing them on to the confined app. The confined
# app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps
# maliciously leak), but instead receives only a thing that it can pass back to the container
# later to restore the ref. See:
# http://www.erights.org/elib/capability/dist-confine.html
# later to restore the ref. See:
# http://www.erights.org/elib/capability/dist-confine.html
client @1;
# The object lives on the "client" or "confined app" end of the connection. Only the client
# knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not
# The object lives on the "client" or "confined app" end of the connection. Only the client
# knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not
# actually know how to persist capabilities at all, so use of this is unusual.
}
struct SturdyRefHostId {
struct VatId {
side @0 :Side;
}
......
......@@ -44,25 +44,23 @@ const ::capnp::_::RawSchema s_9fd69ebc87b9719c = {
};
#endif // !CAPNP_LITE
CAPNP_DEFINE_ENUM(Side_9fd69ebc87b9719c, 9fd69ebc87b9719c);
static const ::capnp::_::AlignedData<35> b_e615e371b1036508 = {
static const ::capnp::_::AlignedData<33> b_d20b909fee733a8e = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
8, 101, 3, 177, 113, 227, 21, 230,
142, 58, 115, 238, 159, 144, 11, 210,
25, 0, 0, 0, 1, 0, 1, 0,
161, 242, 218, 92, 136, 199, 132, 161,
0, 0, 7, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
21, 0, 0, 0, 74, 1, 0, 0,
41, 0, 0, 0, 7, 0, 0, 0,
21, 0, 0, 0, 250, 0, 0, 0,
33, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
37, 0, 0, 0, 63, 0, 0, 0,
29, 0, 0, 0, 63, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 97, 112, 110, 112, 47, 114, 112,
99, 45, 116, 119, 111, 112, 97, 114,
116, 121, 46, 99, 97, 112, 110, 112,
58, 83, 116, 117, 114, 100, 121, 82,
101, 102, 72, 111, 115, 116, 73, 100,
0, 0, 0, 0, 0, 0, 0, 0,
58, 86, 97, 116, 73, 100, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0,
4, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0,
......@@ -81,18 +79,18 @@ static const ::capnp::_::AlignedData<35> b_e615e371b1036508 = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
::capnp::word const* const bp_e615e371b1036508 = b_e615e371b1036508.words;
::capnp::word const* const bp_d20b909fee733a8e = b_d20b909fee733a8e.words;
#if !CAPNP_LITE
static const ::capnp::_::RawSchema* const d_e615e371b1036508[] = {
static const ::capnp::_::RawSchema* const d_d20b909fee733a8e[] = {
&s_9fd69ebc87b9719c,
};
static const uint16_t m_e615e371b1036508[] = {0};
static const uint16_t i_e615e371b1036508[] = {0};
const ::capnp::_::RawBrandedSchema::Dependency bd_e615e371b1036508[] = {
static const uint16_t m_d20b909fee733a8e[] = {0};
static const uint16_t i_d20b909fee733a8e[] = {0};
const ::capnp::_::RawBrandedSchema::Dependency bd_d20b909fee733a8e[] = {
};
const ::capnp::_::RawSchema s_e615e371b1036508 = {
0xe615e371b1036508, b_e615e371b1036508.words, 35, d_e615e371b1036508, m_e615e371b1036508,
1, 1, i_e615e371b1036508, nullptr, nullptr, { &s_e615e371b1036508, nullptr, bd_e615e371b1036508, 0, sizeof(bd_e615e371b1036508) / sizeof(bd_e615e371b1036508[0]), nullptr }
const ::capnp::_::RawSchema s_d20b909fee733a8e = {
0xd20b909fee733a8e, b_d20b909fee733a8e.words, 33, d_d20b909fee733a8e, m_d20b909fee733a8e,
1, 1, i_d20b909fee733a8e, nullptr, nullptr, { &s_d20b909fee733a8e, nullptr, bd_d20b909fee733a8e, 0, sizeof(bd_d20b909fee733a8e) / sizeof(bd_d20b909fee733a8e[0]), nullptr }
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<34> b_b88d09a9c5f39817 = {
......@@ -366,7 +364,7 @@ namespace capnp {
namespace rpc {
namespace twoparty {
CAPNP_DEFINE_STRUCT(SturdyRefHostId, , e615e371b1036508);
CAPNP_DEFINE_STRUCT(VatId, , d20b909fee733a8e);
CAPNP_DEFINE_STRUCT(ProvisionId, , b88d09a9c5f39817);
CAPNP_DEFINE_STRUCT(RecipientId, , 89f389b6fd4082c1);
CAPNP_DEFINE_STRUCT(ThirdPartyCapId, , b47f4979672cb59d);
......
......@@ -20,7 +20,7 @@ enum class Side_9fd69ebc87b9719c: uint16_t {
CLIENT,
};
CAPNP_DECLARE_ENUM(Side, 9fd69ebc87b9719c);
CAPNP_DECLARE_SCHEMA(e615e371b1036508);
CAPNP_DECLARE_SCHEMA(d20b909fee733a8e);
CAPNP_DECLARE_SCHEMA(b88d09a9c5f39817);
CAPNP_DECLARE_SCHEMA(89f389b6fd4082c1);
CAPNP_DECLARE_SCHEMA(b47f4979672cb59d);
......@@ -36,14 +36,14 @@ namespace twoparty {
typedef ::capnp::schemas::Side_9fd69ebc87b9719c Side;
struct SturdyRefHostId {
SturdyRefHostId() = delete;
struct VatId {
VatId() = delete;
class Reader;
class Builder;
class Pipeline;
CAPNP_DECLARE_STRUCT(e615e371b1036508, 1, 0);
CAPNP_DECLARE_STRUCT(d20b909fee733a8e, 1, 0);
};
struct ProvisionId {
......@@ -98,9 +98,9 @@ struct JoinResult {
// =======================================================================================
class SturdyRefHostId::Reader {
class VatId::Reader {
public:
typedef SturdyRefHostId Reads;
typedef VatId Reads;
Reader() = default;
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
......@@ -129,9 +129,9 @@ private:
friend class ::capnp::Orphanage;
};
class SturdyRefHostId::Builder {
class VatId::Builder {
public:
typedef SturdyRefHostId Builds;
typedef VatId Builds;
Builder() = delete; // Deleted to discourage incorrect usage.
// You can explicitly initialize to nullptr instead.
......@@ -156,9 +156,9 @@ private:
};
#if !CAPNP_LITE
class SturdyRefHostId::Pipeline {
class VatId::Pipeline {
public:
typedef SturdyRefHostId Pipelines;
typedef VatId Pipelines;
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
......@@ -550,16 +550,16 @@ private:
// =======================================================================================
inline ::capnp::rpc::twoparty::Side SturdyRefHostId::Reader::getSide() const {
inline ::capnp::rpc::twoparty::Side VatId::Reader::getSide() const {
return _reader.getDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS);
}
inline ::capnp::rpc::twoparty::Side SturdyRefHostId::Builder::getSide() {
inline ::capnp::rpc::twoparty::Side VatId::Builder::getSide() {
return _builder.getDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS);
}
inline void SturdyRefHostId::Builder::setSide( ::capnp::rpc::twoparty::Side value) {
inline void VatId::Builder::setSide( ::capnp::rpc::twoparty::Side value) {
_builder.setDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS, value);
}
......
......@@ -29,7 +29,13 @@
namespace capnp {
typedef VatNetwork<rpc::twoparty::SturdyRefHostId, rpc::twoparty::ProvisionId,
namespace rpc {
namespace twoparty {
typedef VatId SturdyRefHostId; // For backwards-compatibility with version 0.4.
}
}
typedef VatNetwork<rpc::twoparty::VatId, rpc::twoparty::ProvisionId,
rpc::twoparty::RecipientId, rpc::twoparty::ThirdPartyCapId, rpc::twoparty::JoinResult>
TwoPartyVatNetworkBase;
......@@ -50,9 +56,9 @@ public:
// implements VatNetwork -----------------------------------------------------
kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> connectToRefHost(
rpc::twoparty::SturdyRefHostId::Reader ref) override;
kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>> acceptConnectionAsRefHost() override;
kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> connect(
rpc::twoparty::VatId::Reader ref) override;
kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>> accept() override;
private:
class OutgoingMessageImpl;
......@@ -93,13 +99,6 @@ private:
kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override;
kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override;
void introduceTo(TwoPartyVatNetworkBase::Connection& recipient,
rpc::twoparty::ThirdPartyCapId::Builder sendToRecipient,
rpc::twoparty::RecipientId::Builder sendToTarget) override;
ConnectionAndProvisionId connectToIntroduced(
rpc::twoparty::ThirdPartyCapId::Reader capId) override;
kj::Own<TwoPartyVatNetworkBase::Connection> acceptIntroducedConnection(
rpc::twoparty::RecipientId::Reader recipientId) override;
};
} // namespace capnp
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -781,6 +781,11 @@ interface TestKeywordMethods {
return @3 ();
}
struct TestSturdyRef {
hostId @0 :TestSturdyRefHostId;
objectId @1 :AnyPointer;
}
struct TestSturdyRefHostId {
host @0 :Text;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment