#include #include "capnp/rpc-twoparty.h" #include #include #include "test.capnp.h" using namespace capnp; using namespace capnproto_test::capnp; using namespace kj; class TestInterfaceImpl final: public test::TestInterface::Server { public: TestInterfaceImpl(int& callCount); ::kj::Promise foo( test::TestInterface::FooParams::Reader params, test::TestInterface::FooResults::Builder result) override; ::kj::Promise bazAdvanced( ::capnp::CallContext context) override; private: int& callCount; }; class TestExtendsImpl final: public test::TestExtends::Server { public: TestExtendsImpl(int& callCount); ::kj::Promise foo( test::TestInterface::FooParams::Reader params, test::TestInterface::FooResults::Builder result) override; ::kj::Promise graultAdvanced( ::capnp::CallContext context) override; private: int& callCount; }; class TestPipelineImpl final: public test::TestPipeline::Server { public: TestPipelineImpl(int& callCount); ::kj::Promise getCapAdvanced( capnp::CallContext context) override; private: int& callCount; }; TestInterfaceImpl::TestInterfaceImpl(int& callCount): callCount(callCount) {} ::kj::Promise TestInterfaceImpl::foo( test::TestInterface::FooParams::Reader params, test::TestInterface::FooResults::Builder result) { ++callCount; result.setX("foo"); return kj::READY_NOW; } ::kj::Promise TestInterfaceImpl::bazAdvanced( ::capnp::CallContext context) { ++callCount; auto params = context.getParams(); // checkTestMessage(params.getS()); context.releaseParams(); return kj::READY_NOW; } TestExtendsImpl::TestExtendsImpl(int& callCount): callCount(callCount) {} ::kj::Promise TestExtendsImpl::foo( test::TestInterface::FooParams::Reader params, test::TestInterface::FooResults::Builder result) { ++callCount; result.setX("bar"); return kj::READY_NOW; } ::kj::Promise TestExtendsImpl::graultAdvanced( ::capnp::CallContext context) { ++callCount; context.releaseParams(); // initTestMessage(context.getResults()); return kj::READY_NOW; } TestPipelineImpl::TestPipelineImpl(int& callCount): callCount(callCount) {} ::kj::Promise TestPipelineImpl::getCapAdvanced( capnp::CallContext context) { ++callCount; auto params = context.getParams(); auto cap = params.getInCap(); context.releaseParams(); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [this,context](capnp::Response&& response) mutable { auto result = context.getResults(); result.setS("bar"); result.initOutBox().setCap(kj::heap(callCount)); }); } class TestRestorer final: public SturdyRefRestorer { public: TestRestorer(int& callCount): callCount(callCount) {} Capability::Client restore(test::TestSturdyRefObjectId::Reader objectId) override { switch (objectId.getTag()) { case test::TestSturdyRefObjectId::Tag::TEST_INTERFACE: return kj::heap(callCount); // case test::TestSturdyRefObjectId::Tag::TEST_EXTENDS: // return Capability::Client(newBrokenCap("No TestExtends implemented.")); case test::TestSturdyRefObjectId::Tag::TEST_PIPELINE: return kj::heap(callCount); } KJ_UNREACHABLE; } private: int& callCount; }; void runServer(kj::Promise quit, kj::Own stream, int& callCount) { // Set up the server. kj::UnixEventLoop eventLoop; TwoPartyVatNetwork network(eventLoop, *stream, rpc::twoparty::Side::SERVER); TestRestorer restorer(callCount); auto server = makeRpcServer(network, restorer, eventLoop); // Wait until quit promise is fulfilled. eventLoop.wait(kj::mv(quit)); } Capability::Client getPersistentCap(RpcSystem& client, rpc::twoparty::Side side, test::TestSturdyRefObjectId::Tag tag) { // Create the SturdyRefHostId. MallocMessageBuilder hostIdMessage(8); auto hostId = hostIdMessage.initRoot(); hostId.setSide(side); // Create the SturdyRefObjectId. MallocMessageBuilder objectIdMessage(8); objectIdMessage.initRoot().setTag(tag); // Connect to the remote capability. return client.restore(hostId, objectIdMessage.getRoot()); } using boost::asio::ip::tcp; int main() { try { int callCount(0); boost::asio::io_service io_service; tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 49999)); tcp::socket socket(io_service); acceptor.accept(socket); kj::Own stream(AsyncIoStream::wrapFd(socket.native_handle())); auto quitter = kj::newPromiseAndFulfiller(); runServer(kj::mv(quitter.promise), kj::mv(stream), callCount); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; }