diff options
Diffstat (limited to 'host/lib/deps/rpclib/include/rpc/detail')
21 files changed, 920 insertions, 0 deletions
diff --git a/host/lib/deps/rpclib/include/rpc/detail/all.h b/host/lib/deps/rpclib/include/rpc/detail/all.h new file mode 100644 index 000000000..5a060bfb0 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/all.h @@ -0,0 +1,26 @@ +#pragma once + +#ifndef ALL_H_H8MAAYCG +#define ALL_H_H8MAAYCG + +#include "rpc/detail/invoke.h" +#include "rpc/detail/if.h" +#include "rpc/detail/bool.h" + +namespace rpc { +namespace detail { + +//! \brief This type can be used to check multiple conditions. +//! It will be true_type if all its arguments are true. +template <typename... T> struct all : true_ {}; + +template <typename H, typename... T> +struct all<H, T...> + : if_<H, all<T...>, false_> {}; + +} +} + + + +#endif /* end of include guard: ALL_H_H8MAAYCG */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/any.h b/host/lib/deps/rpclib/include/rpc/detail/any.h new file mode 100644 index 000000000..09ffb81cf --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/any.h @@ -0,0 +1,21 @@ +#pragma once + +#ifndef ANY_H_4G3QUOAN +#define ANY_H_4G3QUOAN + +#include "rpc/detail/invoke.h" +#include "rpc/detail/if.h" +#include "rpc/detail/bool.h" + +namespace rpc { +namespace detail { + +//! \brief Evaluates to true_type if any of its arguments is true_type. +template <typename... T> struct any : false_ {}; + +template <typename H, typename... T> +struct any<H, T...> : if_<H, true_, any<T...>> {}; +} +} + +#endif /* end of include guard: ANY_H_4G3QUOAN */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/async_writer.h b/host/lib/deps/rpclib/include/rpc/detail/async_writer.h new file mode 100644 index 000000000..941bb1d8f --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/async_writer.h @@ -0,0 +1,86 @@ +#pragma once + +#ifndef ASYNC_WRITER_H_HQIRH28I +#define ASYNC_WRITER_H_HQIRH28I + +#include <boost/asio.hpp> +#include "rpc/msgpack.hpp" +#include <condition_variable> +#include <deque> +#include <memory> +#include <thread> + +namespace rpc { + +class client; + +namespace detail { + +//! \brief Common logic for classes that have a write queue with async writing. +class async_writer : public std::enable_shared_from_this<async_writer> { +public: + async_writer(boost::asio::io_service *io, + boost::asio::ip::tcp::socket socket) + : socket_(std::move(socket)), write_strand_(*io), exit_(false) {} + + void do_write() { + if (exit_) { + return; + } + auto self(shared_from_this()); + auto &item = write_queue_.front(); + // the data in item remains valid until the handler is called + // since it will still be in the queue physically until then. + boost::asio::async_write( + socket_, boost::asio::buffer(item.data(), item.size()), + write_strand_.wrap( + [this, self](boost::system::error_code ec, std::size_t transferred) { + (void)transferred; + if (!ec) { + write_queue_.pop_front(); + if (write_queue_.size() > 0) { + if (!exit_) { + do_write(); + } + } + } else { + LOG_ERROR("Error while writing to socket: {}", ec); + } + + if (exit_) { + LOG_INFO("Closing socket"); + socket_.shutdown( + boost::asio::ip::tcp::socket::shutdown_both); + socket_.close(); + } + })); + } + + void write(RPCLIB_MSGPACK::sbuffer &&data) { + write_queue_.push_back(std::move(data)); + if (write_queue_.size() > 1) { + return; // there is an ongoing write chain so don't start another + } + + do_write(); + } + + friend class rpc::client; + +protected: + boost::asio::ip::tcp::socket socket_; + boost::asio::strand write_strand_; + std::atomic_bool exit_{false}; + bool exited_ = false; + std::mutex m_exit_; + std::condition_variable cv_exit_; + +private: + std::deque<RPCLIB_MSGPACK::sbuffer> write_queue_; + RPCLIB_CREATE_LOG_CHANNEL(async_writer) +}; + +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: ASYNC_WRITER_H_HQIRH28I */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/bool.h b/host/lib/deps/rpclib/include/rpc/detail/bool.h new file mode 100644 index 000000000..65f37d371 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/bool.h @@ -0,0 +1,21 @@ +#pragma once + +#ifndef BOOL_H_QLG6S5XZ +#define BOOL_H_QLG6S5XZ + +#include "rpc/detail/constant.h" + +namespace rpc { +namespace detail { + +template<bool B> +using bool_ = constant<bool, B>; + +using true_ = bool_<true>; + +using false_ = bool_<false>; + +} +} + +#endif /* end of include guard: BOOL_H_QLG6S5XZ */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/call.h b/host/lib/deps/rpclib/include/rpc/detail/call.h new file mode 100644 index 000000000..b5c9bdce0 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/call.h @@ -0,0 +1,92 @@ +#pragma once + +#ifndef CALL_H_ZXFACADH +#define CALL_H_ZXFACADH + +#include <tuple> +#include "rpc/detail/func_tools.h" +#include "rpc/detail/invoke.h" +#include "rpc/detail/is_specialization_of.h" + +namespace rpc { +namespace detail { + +//! \brief Calls a functor with argument provided directly +template <typename Functor, typename Arg> +auto call(Functor f, Arg &&arg) + -> decltype(f(std::forward<Arg>(arg))) +{ + return f(std::forward<Arg>(arg)); +} + + +// Default behaviour is to assume C++11, overriding RPCLIB_CXX_STANDARD can use +// newer standards: +#if RPCLIB_CXX_STANDARD >= 14 + +template <typename Functor, typename... Args, std::size_t... I> +decltype(auto) call_helper(Functor func, std::tuple<Args...> &¶ms, + std::index_sequence<I...>) { + return func(std::get<I>(params)...); +} + +//! \brief Calls a functor with arguments provided as a tuple +template <typename Functor, typename... Args> +decltype(auto) call(Functor f, std::tuple<Args...> &args) { + return call_helper(f, std::forward<std::tuple<Args...>>(args), + std::index_sequence_for<Args...>{}); +} + +#else + +// N is number of arguments left in tuple to unpack + +template <size_t N> +struct call_helper +{ + template <typename Functor, typename... ArgsT, typename... ArgsF> + static auto call( + Functor f, + std::tuple<ArgsT...>& args_t, + ArgsF&&... args_f) + -> decltype(call_helper<N-1>::call( + f, args_t, std::get<N-1>(args_t), + std::forward<ArgsF>(args_f)...)) + { + return call_helper<N-1>::call( + f, + args_t, + std::get<N-1>(args_t), + std::forward<ArgsF>(args_f)... + ); + } +}; + +template <> +struct call_helper<0> +{ + template <typename Functor, typename... ArgsT, typename... ArgsF> + static auto call( + Functor f, + std::tuple<ArgsT...>&, + ArgsF&&... args_f) + -> decltype(f(std::forward<ArgsF>(args_f)...)) + { + return f(std::forward<ArgsF>(args_f)...); + } +}; + +//! \brief Calls a functor with arguments provided as a tuple +template <typename Functor, typename... ArgsT> +auto call(Functor f, std::tuple<ArgsT...>& args_t) + -> decltype(call_helper<sizeof...(ArgsT)>::call(f, args_t)) +{ + return call_helper<sizeof...(ArgsT)>::call(f, args_t); +} + +#endif + +} +} + +#endif /* end of include guard: CALL_H_ZXFACADH */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/client_error.h b/host/lib/deps/rpclib/include/rpc/detail/client_error.h new file mode 100644 index 000000000..73edd2ebe --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/client_error.h @@ -0,0 +1,39 @@ +#pragma once + +#ifndef RPC_CLIENT_ERROR_H +#define RPC_CLIENT_ERROR_H + +#include <stdexcept> +#include <cstdint> + +namespace rpc { +namespace detail { + +//! \brief Describes an error that is the result of a connected client +//! doing something unexpected (e.g. calling a function that does not exist, +//! wrong number of arguments, etc.) +class client_error : public std::exception { +public: + //! \brief Error codes used for signaling back to clients. These are used + //! to produce google-able error messages (since the msgpack-rpc protocol + //! does not define error handling in any more detail than sending an + //! object). + //! \note Care must be taken to keep these codes stable even between major + //! versions. + enum class code : uint16_t { + no_such_function = 1, + wrong_arity = 2, + protocol_error = 4 + }; + + client_error(code c, const std::string &msg); + + const char *what() const noexcept; + +private: + std::string what_; +}; +} +} + +#endif // RPC_CLIENT_ERROR_H diff --git a/host/lib/deps/rpclib/include/rpc/detail/constant.h b/host/lib/deps/rpclib/include/rpc/detail/constant.h new file mode 100644 index 000000000..1c373b3a2 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/constant.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef CONSTANT_H_5CXUYJEW +#define CONSTANT_H_5CXUYJEW + +#include <type_traits> + +namespace rpc { +namespace detail { + +template<typename T, T I> +struct constant : std::integral_constant<T, I> {}; + +} +} + +#endif /* end of include guard: CONSTANT_H_5CXUYJEW */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/dev_utils.h b/host/lib/deps/rpclib/include/rpc/detail/dev_utils.h new file mode 100644 index 000000000..325320970 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/dev_utils.h @@ -0,0 +1,21 @@ +#pragma once + +#ifndef DEV_UTILS_H_JQSWE2OS +#define DEV_UTILS_H_JQSWE2OS + +#ifdef RPCLIB_LINUX +#include "pthread.h" +#endif + +namespace rpc { +namespace detail { +inline void name_thread(std::string const &name) { + (void)name; +#ifdef RPCLIB_LINUX + pthread_setname_np(pthread_self(), name.c_str()); +#endif +} +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: DEV_UTILS_H_JQSWE2OS */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/func_tools.h b/host/lib/deps/rpclib/include/rpc/detail/func_tools.h new file mode 100644 index 000000000..4f18e482d --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/func_tools.h @@ -0,0 +1,26 @@ +#pragma once + +#ifndef FUNC_TOOLS_H_9FNRD4G2 +#define FUNC_TOOLS_H_9FNRD4G2 + +#include "rpc/detail/invoke.h" +#include "rpc/detail/all.h" +#include "rpc/detail/any.h" + +namespace rpc { +namespace detail { + + +enum class enabled {}; + +template <typename... C> +using enable_if = invoke<std::enable_if<all<C...>::value, enabled>>; + +template <typename... C> +using disable_if = invoke<std::enable_if<!any<C...>::value, enabled>>; + + +} +} + +#endif /* end of include guard: FUNC_TOOLS_H_9FNRD4G2 */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/func_traits.h b/host/lib/deps/rpclib/include/rpc/detail/func_traits.h new file mode 100644 index 000000000..1847d99dc --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/func_traits.h @@ -0,0 +1,77 @@ +#pragma once + +#ifndef FUNC_TRAITS_H_HWIWA6G0 +#define FUNC_TRAITS_H_HWIWA6G0 + +#include "rpc/detail/bool.h" + +namespace rpc { +namespace detail { + +template <int N> +using is_zero = invoke<std::conditional<(N == 0), true_, false_>>; + +template <int N, typename... Ts> +using nth_type = invoke<std::tuple_element<N, std::tuple<Ts...>>>; + +namespace tags { + +// tags for the function traits, used for tag dispatching +struct zero_arg {}; +struct nonzero_arg {}; +struct void_result {}; +struct nonvoid_result {}; + +template <int N> struct arg_count_trait { typedef nonzero_arg type; }; + +template <> struct arg_count_trait<0> { typedef zero_arg type; }; + +template <typename T> struct result_trait { typedef nonvoid_result type; }; + +template <> struct result_trait<void> { typedef void_result type; }; +} + +//! \brief Provides a small function traits implementation that +//! works with a reasonably large set of functors. +template <typename T> +struct func_traits : func_traits<decltype(&T::operator())> {}; + +template <typename C, typename R, typename... Args> +struct func_traits<R (C::*)(Args...)> : func_traits<R (*)(Args...)> {}; + +template <typename C, typename R, typename... Args> +struct func_traits<R (C::*)(Args...) const> : func_traits<R (*)(Args...)> {}; + +template <typename R, typename... Args> struct func_traits<R (*)(Args...)> { + using result_type = R; + using arg_count = std::integral_constant<std::size_t, sizeof...(Args)>; + using args_type = std::tuple<typename std::decay<Args>::type...>; +}; + +template <typename T> +struct func_kind_info : func_kind_info<decltype(&T::operator())> {}; + +template <typename C, typename R, typename... Args> +struct func_kind_info<R (C::*)(Args...)> : func_kind_info<R (*)(Args...)> {}; + +template <typename C, typename R, typename... Args> +struct func_kind_info<R (C::*)(Args...) const> + : func_kind_info<R (*)(Args...)> {}; + +template <typename R, typename... Args> struct func_kind_info<R (*)(Args...)> { + typedef typename tags::arg_count_trait<sizeof...(Args)>::type args_kind; + typedef typename tags::result_trait<R>::type result_kind; +}; + +template <typename F> using is_zero_arg = is_zero<func_traits<F>::arg_count>; + +template <typename F> +using is_single_arg = + invoke<std::conditional<func_traits<F>::arg_count == 1, true_, false_>>; + +template <typename F> +using is_void_result = std::is_void<typename func_traits<F>::result_type>; +} +} + +#endif /* end of include guard: FUNC_TRAITS_H_HWIWA6G0 */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/if.h b/host/lib/deps/rpclib/include/rpc/detail/if.h new file mode 100644 index 000000000..7e4cab4f1 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/if.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef IF_H_1OW9DR7G +#define IF_H_1OW9DR7G + +#include "rpc/detail/invoke.h" + +namespace rpc { +namespace detail { + +template <typename C, typename T, typename F> +using if_ = invoke<std::conditional<C::value, T, F>>; +} +} + +#endif /* end of include guard: IF_H_1OW9DR7G */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/invoke.h b/host/lib/deps/rpclib/include/rpc/detail/invoke.h new file mode 100644 index 000000000..4a4915829 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/invoke.h @@ -0,0 +1,15 @@ +#pragma once + +#ifndef INVOKE_H_0CWMPLUE +#define INVOKE_H_0CWMPLUE + +namespace rpc { +namespace detail { + +template<typename T> +using invoke = typename T::type; + +}} + + +#endif /* end of include guard: INVOKE_H_0CWMPLUE */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/is_specialization_of.h b/host/lib/deps/rpclib/include/rpc/detail/is_specialization_of.h new file mode 100644 index 000000000..c4003cee9 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/is_specialization_of.h @@ -0,0 +1,20 @@ +#pragma once + +#ifndef IS_SPECIALIZATION_OF_H_OPZTARVG +#define IS_SPECIALIZATION_OF_H_OPZTARVG + +#include "rpc/detail/bool.h" + +namespace rpc { +namespace detail { + +template <template <typename...> class Templ, typename T> +struct is_specialization_of : false_ {}; + +template <template <typename...> class Templ, typename... T> +struct is_specialization_of<Templ, Templ<T...>> : true_ {}; + +} +} /* rpc */ + +#endif /* end of include guard: IS_SPECIALIZATION_OF_H_OPZTARVG */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/log.h b/host/lib/deps/rpclib/include/rpc/detail/log.h new file mode 100644 index 000000000..0d5e51c61 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/log.h @@ -0,0 +1,159 @@ +#pragma once + +#ifndef LOG_H_SPSC31OG +#define LOG_H_SPSC31OG + +#ifdef RPCLIB_ENABLE_LOGGING + +#include "format.h" +#include <chrono> +#include <cstdlib> +#include <iomanip> +#include <mutex> +#include <sstream> + +#include <inttypes.h> +#include <math.h> +#include <stdio.h> +#include <time.h> + +#ifdef _MSC_VER +#include <Windows.h> +#endif + +namespace rpc { +namespace detail { +class logger { +public: + static logger &instance() { + static logger inst; + return inst; + } + + template <typename... Args> + void trace(const char *channel, const char *file, const char *func, + std::size_t line, const char *msg, Args... args) { + (void)func; + basic_log("TRACE", channel, + RPCLIB_FMT::format("{} ({}:{})", + RPCLIB_FMT::format(msg, args...), file, + line)); + } + + template <typename... Args> + void debug(const char *channel, const char *file, const char *func, + std::size_t line, const char *msg, Args... args) { + (void)func; + basic_log("DEBUG", channel, + RPCLIB_FMT::format("{} ({}:{})", + RPCLIB_FMT::format(msg, args...), file, + line)); + } + + template <typename... Args> + void warn(const char *channel, const char *msg, Args... args) { + basic_log("WARN", channel, RPCLIB_FMT::format(msg, args...)); + } + + template <typename... Args> + void error(const char *channel, const char *msg, Args... args) { + basic_log("ERROR", channel, RPCLIB_FMT::format(msg, args...)); + } + + template <typename... Args> + void info(const char *channel, const char *msg, Args... args) { + basic_log("INFO", channel, RPCLIB_FMT::format(msg, args...)); + } + +private: + logger() {} + +#ifdef _MSC_VER + static std::string now() { + std::stringstream ss; + SYSTEMTIME t; + GetSystemTime(&t); + ss << RPCLIB_FMT::format("{}-{}-{} {}:{}:{}.{:03}", t.wYear, t.wMonth, + t.wDay, t.wHour, t.wMinute, t.wSecond, + t.wMilliseconds); + return ss.str(); + } +#else + static std::string now() { + std::stringstream ss; + timespec now_t = {}; + clock_gettime(CLOCK_REALTIME, &now_t); + ss << std::put_time( + std::localtime(reinterpret_cast<time_t *>(&now_t.tv_sec)), + "%F %T") + << RPCLIB_FMT::format( + ".{:03}", round(static_cast<double>(now_t.tv_nsec) / 1.0e6)); + return ss.str(); + } +#endif + + void basic_log(const char *severity, const char *channel, + std::string const &msg) { + using RPCLIB_FMT::arg; + std::lock_guard<std::mutex> lock(mut_print_); + RPCLIB_FMT::print("{time:16} {severity:6} {channel:12} {msg:40}\n", + arg("severity", severity), arg("channel", channel), + arg("time", now()), arg("msg", msg)); + } + +private: + std::mutex mut_print_; +}; +} /* detail */ +} /* rpc */ + +#ifdef _MSC_VER +#define RPCLIB_CREATE_LOG_CHANNEL(Name) \ + static constexpr const char *rpc_channel_name = #Name; +#elif defined(__GNUC__) +#define RPCLIB_CREATE_LOG_CHANNEL(Name) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wunused-variable\"") \ + static constexpr const char *rpc_channel_name = #Name; \ + _Pragma("GCC diagnostic pop") +#elif defined(__clang__) + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunused-variable\"") \ + static constexpr const char *rpc_channel_name = #Name; \ + _Pragma("clang diagnostic pop") +#endif + +RPCLIB_CREATE_LOG_CHANNEL(global) + +#define LOG_INFO(...) \ + rpc::detail::logger::instance().info(rpc_channel_name, __VA_ARGS__) + +#define LOG_WARN(...) \ + rpc::detail::logger::instance().warn(rpc_channel_name, __VA_ARGS__) + +#define LOG_ERROR(...) \ + rpc::detail::logger::instance().error(rpc_channel_name, __VA_ARGS__) + +#define LOG_DEBUG(...) \ + rpc::detail::logger::instance().debug(rpc_channel_name, __FILE__, \ + __func__, __LINE__, __VA_ARGS__) + +#define LOG_TRACE(...) \ + rpc::detail::logger::instance().trace(rpc_channel_name, __FILE__, \ + __func__, __LINE__, __VA_ARGS__) + +#define LOG_EXPR(Level, Expr) LOG_##Level("`" #Expr "` = {}", Expr) + +#else + +#define LOG_INFO(...) +#define LOG_WARN(...) +#define LOG_ERROR(...) +#define LOG_DEBUG(...) +#define LOG_TRACE(...) +#define LOG_EXPR(...) +#define RPCLIB_CREATE_LOG_CHANNEL(...) + +#endif + +#endif /* end of include guard: LOG_H_SPSC31OG */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/make_unique.h b/host/lib/deps/rpclib/include/rpc/detail/make_unique.h new file mode 100644 index 000000000..1297aeaab --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/make_unique.h @@ -0,0 +1,31 @@ +#pragma once + +#ifndef MAKE_UNIQUE_H_FOOBAR +#define MAKE_UNIQUE_H_FOOBAR + +#include <memory> + +namespace rpc { +namespace detail { + +// Default behaviour is to assume C++11, overriding RPCLIB_CXX_STANDARD can use +// newer standards: +#if RPCLIB_CXX_STANDARD >= 14 + +using std::make_unique; + +#else + +template<typename T, typename... Ts> +std::unique_ptr<T> make_unique(Ts&&... params) +{ + return std::unique_ptr<T>(new T(std::forward<Ts>(params)...)); +} + +#endif + +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: MAKE_UNIQUE_H_FOOBAR */ + diff --git a/host/lib/deps/rpclib/include/rpc/detail/not.h b/host/lib/deps/rpclib/include/rpc/detail/not.h new file mode 100644 index 000000000..9d78cafb3 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/not.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef NOT_H_0MEGQWII +#define NOT_H_0MEGQWII + +#include "rpc/detail/bool.h" + +namespace rpc { +namespace detail { + +template<typename B> +using not_ = bool_<!B::value>; + +} +} + +#endif /* end of include guard: NOT_H_0MEGQWII */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/pimpl.h b/host/lib/deps/rpclib/include/rpc/detail/pimpl.h new file mode 100644 index 000000000..526f788ac --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/pimpl.h @@ -0,0 +1,10 @@ +#pragma once + +#ifndef PIMPL_H_TV7E3C9K +#define PIMPL_H_TV7E3C9K + +//! \brief Declares a pimpl pointer. +#define RPCLIB_DECLARE_PIMPL() \ + struct impl; std::unique_ptr<impl> pimpl; + +#endif /* end of include guard: PIMPL_H_TV7E3C9K */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/response.h b/host/lib/deps/rpclib/include/rpc/detail/response.h new file mode 100644 index 000000000..96131b1a7 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/response.h @@ -0,0 +1,119 @@ +#pragma once + +#ifndef RESPONSE_H_MVRZEKPX +#define RESPONSE_H_MVRZEKPX + +#include "rpc/detail/log.h" +#include "rpc/detail/make_unique.h" +#include "rpc/msgpack.hpp" +#include "rpc/config.h" + +namespace rpc { +namespace detail { + +//! \brief Represents a response and creates a msgpack to be sent back +//! as per the msgpack-rpc spec. +class response { +public: + //! \brief Creates a response that represents a normal return value. + //! \param id The sequence id (as per protocol). + //! \param result The return value to store in the response. + //! \tparam T Any msgpack-able type. + //! \note If there is both an error and result in the response, + //! the result will be discarded while packing the data. + template <typename T> static response make_result(uint32_t id, T &&result); + + //! \brief Creates a response that represents an error. + //! \param id The sequence id (as per protocol). + //! \param error The error value to store in the response. + //! \tparam T Any msgpack-able type. + template <typename T> static response make_error(uint32_t id, T &&error); + + + //! \brief Constructs a response from RPCLIB_MSGPACK::object (useful when + //! reading a response from a stream). + response(RPCLIB_MSGPACK::object_handle o); + + //! \brief Gets the response data as a RPCLIB_MSGPACK::sbuffer. + RPCLIB_MSGPACK::sbuffer get_data() const; + + //! \brief Moves the specified object_handle into the response + //! as a result. + //! \param r The result to capture. + void capture_result(RPCLIB_MSGPACK::object_handle &r); + + //! \brief Moves the specified object_handle into the response as an error. + //! \param e The error to capture. + void capture_error(RPCLIB_MSGPACK::object_handle &e); + + //! \brief Returns the call id/index used to identify which call + //! this response corresponds to. + uint32_t get_id() const; + + //! \brief Returns the error object stored in the response. Can + //! be empty. + std::shared_ptr<RPCLIB_MSGPACK::object_handle> get_error() const; + + //! \brief Returns the result stored in the response. Can be empty. + std::shared_ptr<RPCLIB_MSGPACK::object_handle> get_result() const; + + //! \brief Gets an empty response which means "no response" (not to be + //! confused with void return, i.e. this means literally + //! "don't write the response to the socket") + static response empty(); + + //! \brief If true, this response is empty (\see empty()) + bool is_empty() const; + + //! \brief The type of a response, according to the msgpack-rpc spec + using response_type = + std::tuple<uint32_t, uint32_t, RPCLIB_MSGPACK::object, RPCLIB_MSGPACK::object>; + +private: + //! \brief Default constructor for responses. + response(); + + uint32_t id_; + // I really wish to avoid shared_ptr here but at this point asio does not + // work with move-only handlers in post() and I need to capture responses + // in lambdas. + std::shared_ptr<RPCLIB_MSGPACK::object_handle> error_; + std::shared_ptr<RPCLIB_MSGPACK::object_handle> result_; + bool empty_; + RPCLIB_CREATE_LOG_CHANNEL(response) +}; + +template <typename T> +inline response response::make_result(uint32_t id, T &&result) { + auto z = rpc::detail::make_unique<RPCLIB_MSGPACK::zone>(); + RPCLIB_MSGPACK::object o(std::forward<T>(result), *z); + response inst; + inst.id_ = id; + inst.result_ = std::make_shared<RPCLIB_MSGPACK::object_handle>(o, std::move(z)); + return inst; +} + +template <> +inline response +response::make_result(uint32_t id, std::unique_ptr<RPCLIB_MSGPACK::object_handle> &&r) { + response inst; + inst.id_ = id; + inst.result_ = std::move(r); + return inst; +} + +template <typename T> +inline response response::make_error(uint32_t id, T &&error) { + auto z = rpc::detail::make_unique<RPCLIB_MSGPACK::zone>(); + RPCLIB_MSGPACK::object o(std::forward<T>(error), *z); + response inst; + inst.id_ = id; + inst.error_ = std::make_shared<RPCLIB_MSGPACK::object_handle>(o, std::move(z)); + return inst; +} + +} /* detail */ + +} /* rpc */ + +#endif /* end of include guard: RESPONSE_H_MVRZEKPX */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/server_session.h b/host/lib/deps/rpclib/include/rpc/detail/server_session.h new file mode 100644 index 000000000..963b082ec --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/server_session.h @@ -0,0 +1,48 @@ +#pragma once + +#ifndef SESSION_H_5KG6ZMAB +#define SESSION_H_5KG6ZMAB + +#include <boost/asio.hpp> +#include <memory> +#include <vector> + +#include "rpc/config.h" +#include "rpc/msgpack.hpp" + +#include "rpc/dispatcher.h" +#include "rpc/detail/async_writer.h" +#include "rpc/detail/log.h" + +namespace rpc { + +class server; + +namespace detail { + +class server_session : public async_writer { +public: + server_session(server *srv, boost::asio::io_service *io, + boost::asio::ip::tcp::socket socket, + std::shared_ptr<dispatcher> disp, bool suppress_exceptions); + void start(); + + void close(); + +private: + void do_read(); + +private: + server* parent_; + boost::asio::io_service *io_; + boost::asio::strand read_strand_; + std::shared_ptr<dispatcher> disp_; + RPCLIB_MSGPACK::unpacker pac_; + RPCLIB_MSGPACK::sbuffer output_buf_; + const bool suppress_exceptions_; + RPCLIB_CREATE_LOG_CHANNEL(session) +}; +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: SESSION_H_5KG6ZMAB */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/thread_group.h b/host/lib/deps/rpclib/include/rpc/detail/thread_group.h new file mode 100644 index 000000000..8905a7150 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/thread_group.h @@ -0,0 +1,40 @@ +#pragma once + +#ifndef THREAD_GROUP_H_MQSLWGKD +#define THREAD_GROUP_H_MQSLWGKD + +#include <thread> +#include <vector> + +namespace rpc { +namespace detail { + +class thread_group { +public: + thread_group() {} + thread_group(thread_group const &) = delete; + + void create_threads(std::size_t thread_count, std::function<void()> func) { + for (std::size_t i = 0; i < thread_count; ++i) { + threads_.push_back(std::thread(func)); + } + } + + void join_all() { + for (auto &t : threads_) { + if (t.joinable()) { + t.join(); + } + } + } + + ~thread_group() { join_all(); } + +private: + std::vector<std::thread> threads_; +}; + +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: THREAD_GROUP_H_MQSLWGKD */ diff --git a/host/lib/deps/rpclib/include/rpc/detail/util.h b/host/lib/deps/rpclib/include/rpc/detail/util.h new file mode 100644 index 000000000..302cb93b7 --- /dev/null +++ b/host/lib/deps/rpclib/include/rpc/detail/util.h @@ -0,0 +1,19 @@ +#pragma once + +#ifndef UTIL_H_YRIZ63UJ +#define UTIL_H_YRIZ63UJ + +#include "rpc/msgpack.hpp" +#include "rpc/detail/make_unique.h" + +namespace rpc { +namespace detail { +template <typename T> RPCLIB_MSGPACK::object_handle pack(T &&o) { + auto z = rpc::detail::make_unique<RPCLIB_MSGPACK::zone>(); + RPCLIB_MSGPACK::object obj(std::forward<T>(o), *z); + return RPCLIB_MSGPACK::object_handle(obj, std::move(z)); +} +} /* detail */ +} /* rpc */ + +#endif /* end of include guard: UTIL_H_YRIZ63UJ */ |