Commit 202232b3 authored by Kenton Varda's avatar Kenton Varda

Merge branch 'master' of github.com:kentonv/capnproto

parents 286b749e 568d8e2c
......@@ -5,6 +5,7 @@ under the same MIT license terms as the rest of the library.
Kenton Varda <temporal@gmail.com>: Primary Author
Jason Choy <jjwchoy@gmail.com>: kj/threadlocal.h and other iOS tweaks, `name` annotation in C++ code generator
Remy Blank <rblank@google.com> (contributions copyright Google Inc.): KJ Timers
Joshua Warner <joshuawarner32@gmail.com>: cmake build
This file does not list people who maintain their own Cap'n Proto
implementations as separate projects. Those people are awesome too! :)
project(Private)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -std=c++11")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest" AND IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/gtest")
add_subdirectory(gtest)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gtest/include)
else()
message(FATAL_ERROR "Please use setup-cmake.sh to download gtest before running the cmake build")
endif()
include(CTest)
add_subdirectory(src)
#! /usr/bin/env bash
set -euo pipefail
if [ ! -e gtest ]; then
echo "================================================================================"
echo "Fetching Google Test code..."
echo "================================================================================"
svn checkout http://googletest.googlecode.com/svn/tags/release-1.7.0 gtest
fi
echo "================================================================================"
echo "Done"
echo "================================================================================"
echo
echo "Ready to run cmake (no support for installing yet). For example:"
echo " mkdir build && cd build && cmake .. -G 'Unix Makefiles' && make -j6 check"
project(Private)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -std=c++11")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_library(kj
kj/common.c++
kj/units.c++
kj/memory.c++
kj/refcount.c++
kj/array.c++
kj/string.c++
kj/string-tree.c++
kj/exception.c++
kj/debug.c++
kj/arena.c++
kj/io.c++
kj/mutex.c++
kj/thread.c++
kj/main.c++
kj/parse/char.c++
)
add_library(kj-async
kj/async.c++
kj/async-unix.c++
kj/async-io.c++
)
add_library(capnp
capnp/c++.capnp.c++
capnp/blob.c++
capnp/arena.c++
capnp/layout.c++
capnp/list.c++
capnp/any.c++
capnp/message.c++
capnp/schema.capnp.c++
capnp/schema.c++
capnp/schema-loader.c++
capnp/dynamic.c++
capnp/stringify.c++
capnp/serialize.c++
capnp/serialize-packed.c++
)
add_library(capnp-rpc
capnp/serialize-async.c++
capnp/capability.c++
capnp/dynamic-capability.c++
capnp/rpc.c++
capnp/rpc.capnp.c++
capnp/rpc-twoparty.c++
capnp/rpc-twoparty.capnp.c++
capnp/ez-rpc.c++
)
add_library(capnpc
capnp/compiler/md5.c++
capnp/compiler/error-reporter.c++
capnp/compiler/lexer.capnp.c++
capnp/compiler/lexer.c++
capnp/compiler/grammar.capnp.c++
capnp/compiler/parser.c++
capnp/compiler/node-translator.c++
capnp/compiler/compiler.c++
capnp/schema-parser.c++
)
add_executable(capnp-tool
capnp/compiler/module-loader.c++
capnp/compiler/capnp.c++
)
target_link_libraries(capnp-tool capnpc capnp kj)
set_target_properties(capnp-tool PROPERTIES OUTPUT_NAME capnp)
add_executable(capnpc_cpp
capnp/compiler/capnpc-c++.c++
)
target_link_libraries(capnpc_cpp capnp kj)
set_target_properties(capnpc_cpp PROPERTIES OUTPUT_NAME capnpc-c++)
set(test_capnp_files
capnp/test.capnp
capnp/test-import.capnp
capnp/test-import2.capnp
)
set(test_capnp_cpp_files)
set(test_capnp_header_files)
set(test_capnp_capnp_files)
foreach(_file ${test_capnp_files})
list(APPEND test_capnp_cpp_files ${CMAKE_CURRENT_BINARY_DIR}/${_file}.c++)
list(APPEND test_capnp_header_files ${CMAKE_CURRENT_BINARY_DIR}/${_file}.h)
get_filename_component(_capnp_abs ${_file} ABSOLUTE)
list(APPEND test_capnp_capnp_files ${_capnp_abs})
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/${_file}.capnp.c++
PROPERTIES GENERATED TRUE)
endforeach()
add_custom_command(
OUTPUT
${test_capnp_cpp_files}
${test_capnp_header_files}
COMMAND capnp-tool compile
-o $<TARGET_FILE:capnpc_cpp>
--src-prefix=${CMAKE_CURRENT_SOURCE_DIR}
-I${CMAKE_CURRENT_SOURCE_DIR}
${test_capnp_capnp_files}
DEPENDS capnp-tool capnpc_cpp ${test_capnp_files})
add_library(capnp_test_lib ${test_capnp_cpp_files})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(capnp-tests
kj/common-test.c++
kj/memory-test.c++
kj/refcount-test.c++
kj/array-test.c++
kj/string-test.c++
kj/string-tree-test.c++
kj/exception-test.c++
kj/debug-test.c++
kj/arena-test.c++
kj/units-test.c++
kj/tuple-test.c++
kj/one-of-test.c++
kj/function-test.c++
kj/io-test.c++
kj/mutex-test.c++
kj/threadlocal-test.c++
kj/threadlocal-pthread-test.c++
kj/async-test.c++
kj/async-unix-test.c++
kj/async-io-test.c++
kj/parse/common-test.c++
kj/parse/char-test.c++
capnp/common-test.c++
capnp/blob-test.c++
capnp/endian-test.c++
capnp/endian-fallback-test.c++
capnp/endian-reverse-test.c++
capnp/layout-test.c++
capnp/any-test.c++
capnp/message-test.c++
capnp/capability-test.c++
capnp/schema-test.c++
capnp/schema-loader-test.c++
capnp/dynamic-test.c++
capnp/stringify-test.c++
capnp/encoding-test.c++
capnp/orphan-test.c++
capnp/serialize-test.c++
capnp/serialize-async-test.c++
capnp/serialize-packed-test.c++
capnp/rpc-test.c++
capnp/rpc-twoparty-test.c++
capnp/ez-rpc-test.c++
capnp/test-util.c++
capnp/compiler/lexer-test.c++
capnp/compiler/md5-test.c++
)
target_link_libraries(capnp-tests
capnp_test_lib
capnpc
capnp-rpc
capnp
kj-async
kj
gtest
gtest_main
)
add_executable(capnp-evolution-tests capnp/compiler/evolution-test.c++)
target_link_libraries(capnp-evolution-tests
capnp_test_lib
capnpc
capnp-rpc
capnp
kj-async
kj
gtest
gtest_main
)
add_test(NAME capnp-tests-run COMMAND capnp-tests)
add_test(NAME capnp-evolution-tests-run COMMAND capnp-evolution-tests)
# Sadly, we can't use the 'test' target, as that's coopted by ctest
add_custom_target(check ${CMAKE_CTEST_COMMAND} -V)
add_dependencies(check capnp-tests)
add_dependencies(check capnp-evolution-tests)
......@@ -23,7 +23,7 @@
# The structures in this file correspond to the AST of the Cap'n Proto schema language.
#
# This file is intended to be used internally by capnpc. Mostly, it is useful because it is more
# convenient that defining data classes in C++, particularly where variant types (unions) are
# convenient than defining data classes in C++, particularly where variant types (unions) are
# needed. Over time, this file may change in backwards-incompatible ways.
using Cxx = import "/capnp/c++.capnp";
......
......@@ -80,9 +80,9 @@ struct EzRpcClient::Impl {
TwoPartyVatNetwork network;
RpcSystem<rpc::twoparty::SturdyRefHostId> rpcSystem;
ClientContext(kj::Own<kj::AsyncIoStream>&& stream)
ClientContext(kj::Own<kj::AsyncIoStream>&& stream, ReaderOptions readerOpts)
: stream(kj::mv(stream)),
network(*this->stream, rpc::twoparty::Side::CLIENT),
network(*this->stream, rpc::twoparty::Side::CLIENT, readerOpts),
rpcSystem(makeRpcClient(network)) {}
Capability::Client restore(kj::StringPtr name) {
......@@ -102,39 +102,44 @@ struct EzRpcClient::Impl {
kj::Maybe<kj::Own<ClientContext>> clientContext;
// Filled in before `setupPromise` resolves.
Impl(kj::StringPtr serverAddress, uint defaultPort)
Impl(kj::StringPtr serverAddress, uint defaultPort,
ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()),
setupPromise(context->getIoProvider().getNetwork()
.parseAddress(serverAddress, defaultPort)
.then([](kj::Own<kj::NetworkAddress>&& addr) {
.then([readerOpts](kj::Own<kj::NetworkAddress>&& addr) {
return addr->connect();
}).then([this](kj::Own<kj::AsyncIoStream>&& stream) {
clientContext = kj::heap<ClientContext>(kj::mv(stream));
}).then([this, readerOpts](kj::Own<kj::AsyncIoStream>&& stream) {
clientContext = kj::heap<ClientContext>(kj::mv(stream),
readerOpts);
}).fork()) {}
Impl(const struct sockaddr* serverAddress, uint addrSize)
Impl(const struct sockaddr* serverAddress, uint addrSize,
ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()),
setupPromise(context->getIoProvider().getNetwork()
.getSockaddr(serverAddress, addrSize)->connect()
.then([this](kj::Own<kj::AsyncIoStream>&& stream) {
clientContext = kj::heap<ClientContext>(kj::mv(stream));
.then([this, readerOpts](kj::Own<kj::AsyncIoStream>&& stream) {
clientContext = kj::heap<ClientContext>(kj::mv(stream),
readerOpts);
}).fork()) {}
Impl(int socketFd)
Impl(int socketFd, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()),
setupPromise(kj::Promise<void>(kj::READY_NOW).fork()),
clientContext(kj::heap<ClientContext>(
context->getLowLevelIoProvider().wrapSocketFd(socketFd))) {}
context->getLowLevelIoProvider().wrapSocketFd(socketFd),
readerOpts)) {}
};
EzRpcClient::EzRpcClient(kj::StringPtr serverAddress, uint defaultPort)
: impl(kj::heap<Impl>(serverAddress, defaultPort)) {}
EzRpcClient::EzRpcClient(kj::StringPtr serverAddress, uint defaultPort, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(serverAddress, defaultPort, readerOpts)) {}
EzRpcClient::EzRpcClient(const struct sockaddr* serverAddress, uint addrSize)
: impl(kj::heap<Impl>(serverAddress, addrSize)) {}
EzRpcClient::EzRpcClient(const struct sockaddr* serverAddress, uint addrSize, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(serverAddress, addrSize, readerOpts)) {}
EzRpcClient::EzRpcClient(int socketFd)
: impl(kj::heap<Impl>(socketFd)) {}
EzRpcClient::EzRpcClient(int socketFd, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(socketFd, readerOpts)) {}
EzRpcClient::~EzRpcClient() noexcept(false) {}
......@@ -192,50 +197,51 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
TwoPartyVatNetwork network;
RpcSystem<rpc::twoparty::SturdyRefHostId> rpcSystem;
ServerContext(kj::Own<kj::AsyncIoStream>&& stream, SturdyRefRestorer<Text>& restorer)
ServerContext(kj::Own<kj::AsyncIoStream>&& stream, SturdyRefRestorer<Text>& restorer,
ReaderOptions readerOpts)
: stream(kj::mv(stream)),
network(*this->stream, rpc::twoparty::Side::SERVER),
network(*this->stream, rpc::twoparty::Side::SERVER, readerOpts),
rpcSystem(makeRpcServer(network, restorer)) {}
};
Impl(kj::StringPtr bindAddress, uint defaultPort)
Impl(kj::StringPtr bindAddress, uint defaultPort, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) {
auto paf = kj::newPromiseAndFulfiller<uint>();
portPromise = paf.promise.fork();
tasks.add(context->getIoProvider().getNetwork().parseAddress(bindAddress, defaultPort)
.then(kj::mvCapture(paf.fulfiller,
[this](kj::Own<kj::PromiseFulfiller<uint>>&& portFulfiller,
kj::Own<kj::NetworkAddress>&& addr) {
[this, readerOpts](kj::Own<kj::PromiseFulfiller<uint>>&& portFulfiller,
kj::Own<kj::NetworkAddress>&& addr) {
auto listener = addr->listen();
portFulfiller->fulfill(listener->getPort());
acceptLoop(kj::mv(listener));
acceptLoop(kj::mv(listener), readerOpts);
})));
}
Impl(struct sockaddr* bindAddress, uint addrSize)
Impl(struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts)
: 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));
acceptLoop(kj::mv(listener), readerOpts);
}
Impl(int socketFd, uint port)
Impl(int socketFd, uint port, ReaderOptions readerOpts)
: context(EzRpcContext::getThreadLocal()),
portPromise(kj::Promise<uint>(port).fork()),
tasks(*this) {
acceptLoop(context->getLowLevelIoProvider().wrapListenSocketFd(socketFd));
acceptLoop(context->getLowLevelIoProvider().wrapListenSocketFd(socketFd), readerOpts);
}
void acceptLoop(kj::Own<kj::ConnectionReceiver>&& listener) {
void acceptLoop(kj::Own<kj::ConnectionReceiver>&& listener, ReaderOptions readerOpts) {
auto ptr = listener.get();
tasks.add(ptr->accept().then(kj::mvCapture(kj::mv(listener),
[this](kj::Own<kj::ConnectionReceiver>&& listener,
kj::Own<kj::AsyncIoStream>&& connection) {
acceptLoop(kj::mv(listener));
[this, readerOpts](kj::Own<kj::ConnectionReceiver>&& listener,
kj::Own<kj::AsyncIoStream>&& connection) {
acceptLoop(kj::mv(listener), readerOpts);
auto server = kj::heap<ServerContext>(kj::mv(connection), *this);
auto server = kj::heap<ServerContext>(kj::mv(connection), *this, readerOpts);
// Arrange to destroy the server context when all references are gone, or when the
// EzRpcServer is destroyed (which will destroy the TaskSet).
......@@ -258,14 +264,16 @@ struct EzRpcServer::Impl final: public SturdyRefRestorer<Text>, public kj::TaskS
}
};
EzRpcServer::EzRpcServer(kj::StringPtr bindAddress, uint defaultPort)
: impl(kj::heap<Impl>(bindAddress, defaultPort)) {}
EzRpcServer::EzRpcServer(kj::StringPtr bindAddress, uint defaultPort,
ReaderOptions readerOpts)
: impl(kj::heap<Impl>(bindAddress, defaultPort, readerOpts)) {}
EzRpcServer::EzRpcServer(struct sockaddr* bindAddress, uint addrSize)
: impl(kj::heap<Impl>(bindAddress, addrSize)) {}
EzRpcServer::EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
ReaderOptions readerOpts)
: impl(kj::heap<Impl>(bindAddress, addrSize, readerOpts)) {}
EzRpcServer::EzRpcServer(int socketFd, uint port)
: impl(kj::heap<Impl>(socketFd, port)) {}
EzRpcServer::EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts)
: impl(kj::heap<Impl>(socketFd, port, readerOpts)) {}
EzRpcServer::~EzRpcServer() noexcept(false) {}
......
......@@ -23,6 +23,7 @@
#define CAPNP_EZ_RPC_H_
#include "rpc.h"
#include "message.h"
struct sockaddr;
......@@ -91,7 +92,8 @@ class EzRpcClient {
// - `TwoPartyVatNetwork` in `capnp/rpc-twoparty.h`.
public:
explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0);
explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0,
ReaderOptions readerOpts = ReaderOptions());
// Construct a new EzRpcClient and connect to the given address. The connection is formed in
// the background -- if it fails, calls to capabilities returned by importCap() will fail with an
// appropriate exception.
......@@ -101,13 +103,23 @@ public:
//
// The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info
// on the address format, but basically it's what you'd expect.
//
// `readerOpts` is the ReaderOptions structure used by capnproto to limit the traversal of
// messages. If not specified, a default value of 8M max word traversal and a nesting limit of 64
// deep.
// 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);
EzRpcClient(const struct sockaddr* serverAddress, uint addrSize,
ReaderOptions readerOpts = ReaderOptions());
// Like the above constructor, but connects to an already-resolved socket address. Any address
// format supported by `kj::Network` in `kj/async-io.h` is accepted.
explicit EzRpcClient(int socketFd);
explicit EzRpcClient(int socketFd, ReaderOptions readerOpts = ReaderOptions());
// Create a client on top of an already-connected socket.
// `readerOpts` acts as in the first constructor.
~EzRpcClient() noexcept(false);
......@@ -138,7 +150,8 @@ class EzRpcServer {
// The server counterpart to `EzRpcClient`. See `EzRpcClient` for an example.
public:
explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0);
explicit EzRpcServer(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.
//
......@@ -152,14 +165,23 @@ public:
// The server might not begin listening immediately, especially if `bindAddress` needs to be
// resolved. If you need to wait until the server is definitely up, wait on the promise returned
// by `getPort()`.
EzRpcServer(struct sockaddr* bindAddress, uint addrSize);
//
// `readerOpts` is the ReaderOptions structure used by capnproto to limit the traversal of
// messages. If not specified, a default value of 8M max word traversal and a nesting limit of 64
// deep.
// 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.
EzRpcServer(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);
EzRpcServer(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.
~EzRpcServer() noexcept(false);
......
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