#pragma once #include "capnp/dynamic.h" #include #include "capnp/rpc-twoparty.h" #include "Python.h" #include "capabilityHelper.h" capnp::Capability::Client bootstrapHelper(capnp::RpcSystem& client) { capnp::MallocMessageBuilder hostIdMessage(8); auto hostId = hostIdMessage.initRoot(); hostId.setSide(capnp::rpc::twoparty::Side::SERVER); return client.bootstrap(hostId); } capnp::Capability::Client bootstrapHelperServer(capnp::RpcSystem& client) { capnp::MallocMessageBuilder hostIdMessage(8); auto hostId = hostIdMessage.initRoot(); hostId.setSide(capnp::rpc::twoparty::Side::CLIENT); return client.bootstrap(hostId); } class ErrorHandler : public kj::TaskSet::ErrorHandler { void taskFailed(kj::Exception&& exception) override { kj::throwFatalException(kj::mv(exception)); } }; struct ServerContext { kj::Own stream; capnp::TwoPartyVatNetwork network; capnp::RpcSystem rpcSystem; ServerContext(kj::Own&& stream, capnp::Capability::Client client, capnp::ReaderOptions & opts) : stream(kj::mv(stream)), network(*this->stream, capnp::rpc::twoparty::Side::SERVER, opts), rpcSystem(makeRpcServer(network, client)) {} }; void acceptLoop(kj::TaskSet & tasks, capnp::Capability::Client client, kj::Own&& listener, capnp::ReaderOptions & opts) { auto ptr = listener.get(); tasks.add(ptr->accept().then(kj::mvCapture(kj::mv(listener), [&, client, opts](kj::Own&& listener, kj::Own&& connection) mutable { acceptLoop(tasks, client, kj::mv(listener), opts); auto server = kj::heap(kj::mv(connection), client, opts); // Arrange to destroy the server context when all references are gone, or when the // EzRpcServer is destroyed (which will destroy the TaskSet). tasks.add(server->network.onDisconnect().attach(kj::mv(server))); }))); } kj::Promise> connectServer(kj::TaskSet & tasks, capnp::Capability::Client client, kj::AsyncIoProvider * provider, kj::StringPtr bindAddress, capnp::ReaderOptions & opts) { auto paf = kj::newPromiseAndFulfiller(); auto portPromise = paf.promise.fork(); tasks.add(provider->getNetwork().parseAddress(bindAddress) .then(kj::mvCapture(paf.fulfiller, [&, client, opts](kj::Own>&& portFulfiller, kj::Own&& addr) mutable { auto listener = addr->listen(); portFulfiller->fulfill(listener->getPort()); acceptLoop(tasks, client, kj::mv(listener), opts); }))); return portPromise.addBranch().then([&](unsigned int port) { return stealPyRef(PyLong_FromUnsignedLong(port)); }); }