diff --git a/example/client/get/main.cpp b/example/client/get/main.cpp index 7b891e09..5d24a93d 100644 --- a/example/client/get/main.cpp +++ b/example/client/get/main.cpp @@ -75,10 +75,10 @@ class session // Enable compression #ifdef BOOST_RTS_HAS_BROTLI - req_.set(field::accept_encoding, "br"); + req_.append(field::accept_encoding, "br"); #endif #ifdef BOOST_RTS_HAS_ZLIB - req_.set(field::accept_encoding, "deflate, gzip"); + req_.append(field::accept_encoding, "deflate, gzip"); #endif // Keep original URL for possible redirect diff --git a/example/client/jsonrpc/CMakeLists.txt b/example/client/jsonrpc/CMakeLists.txt index 52c4b211..d9cb81d7 100644 --- a/example/client/jsonrpc/CMakeLists.txt +++ b/example/client/jsonrpc/CMakeLists.txt @@ -37,18 +37,32 @@ if (WIN32) target_link_libraries(http_io_example_client_jsonrpc_lib PUBLIC crypt32) endif() +# CPP11 Example add_executable(http_io_example_client_jsonrpc_cpp11 cpp11.cpp eth_methods.hpp Jamfile) +set_property(TARGET http_io_example_client_jsonrpc_cpp11 + PROPERTY FOLDER "examples") target_link_libraries(http_io_example_client_jsonrpc_cpp11 PRIVATE http_io_example_client_jsonrpc_lib) - set_property(TARGET http_io_example_client_jsonrpc_cpp11 - PROPERTY FOLDER "examples") +if (TARGET boost_rts_zlib) + target_link_libraries(http_io_example_client_jsonrpc_cpp11 PRIVATE boost_rts_zlib) +endif() +if (TARGET boost_rts_brotli) + target_link_libraries(http_io_example_client_jsonrpc_cpp11 PRIVATE boost_rts_brotli) +endif() +# CPP20 Example if (CMAKE_CXX_STANDARD EQUAL 20) add_executable(http_io_example_client_jsonrpc_cpp20 cpp20.cpp eth_methods.hpp Jamfile) + set_property(TARGET http_io_example_client_jsonrpc_cpp20 + PROPERTY FOLDER "examples") target_link_libraries(http_io_example_client_jsonrpc_cpp20 PRIVATE http_io_example_client_jsonrpc_lib) - set_property(TARGET http_io_example_client_jsonrpc_cpp20 - PROPERTY FOLDER "examples") + if (TARGET boost_rts_zlib) + target_link_libraries(http_io_example_client_jsonrpc_cpp20 PRIVATE boost_rts_zlib) + endif() + if (TARGET boost_rts_brotli) + target_link_libraries(http_io_example_client_jsonrpc_cpp20 PRIVATE boost_rts_brotli) + endif() endif () diff --git a/example/client/jsonrpc/cpp11.cpp b/example/client/jsonrpc/cpp11.cpp index 4b4ee6f1..3290b4f2 100644 --- a/example/client/jsonrpc/cpp11.cpp +++ b/example/client/jsonrpc/cpp11.cpp @@ -12,7 +12,9 @@ #include "eth_methods.hpp" #include +#include #include +#include #include #include @@ -60,7 +62,8 @@ class session return fail(ec, "connect"); // Get Ethereum node client software and version - client_[web3_clientVersion]( + client_.async_call( + web3_clientVersion, std::bind(&session::on_clientVersion, this, _1, _2)); } @@ -76,7 +79,8 @@ class session << version << '\n'; // Get the latest block number - client_[eth_blockNumber]( + client_.async_call( + eth_blockNumber, std::bind(&session::on_blockNumber, this, _1, _2)); } @@ -90,9 +94,10 @@ class session std::cout << "Block height: " << block_num << '\n'; - + // Get block details - client_[eth_getBlockByNumber]( + client_.async_call( + eth_getBlockByNumber, { block_num, false }, std::bind(&session::on_getBlockByNumber, this, _1, _2)); } @@ -110,7 +115,8 @@ class session std::cout<< "Transactions: " << block["transactions"].as_array().size() << '\n'; // Get account balance - client_[eth_getBalance]( + client_.async_call( + eth_getBalance, { "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae", block["number"] @@ -128,9 +134,10 @@ class session std::cout << "Balance: " << balance << '\n'; - + // Estimate gas for a transfer - client_[eth_estimateGas]( + client_.async_call( + eth_estimateGas, { json::object { @@ -152,9 +159,10 @@ class session std::cout << "Gas estimate: " << gas_estimate << '\n'; - + // Get the current gas price - client_[eth_gasPrice]( + client_.async_call( + eth_gasPrice, std::bind(&session::on_gasPrice, this, _1, _2)); } @@ -194,8 +202,8 @@ class session void fail(const jsonrpc::error& error) { - if(!error.object().empty()) - std::cerr << error.object() << " "; + if(!error.info().empty()) + std::cerr << error.info() << " "; std::cerr << error.code().what() << "\n"; } }; @@ -233,12 +241,20 @@ main(int, char*[]) { http_proto::response_parser::config cfg; cfg.min_buffer = 64 * 1024; + #ifdef BOOST_RTS_HAS_BROTLI + cfg.apply_brotli_decoder = true; + rts::brotli::install_decode_service(rts_ctx); + #endif + #ifdef BOOST_RTS_HAS_ZLIB + cfg.apply_deflate_decoder = true; + cfg.apply_gzip_decoder = true; + rts::zlib::install_inflate_service(rts_ctx); + #endif http_proto::install_parser_service(rts_ctx, cfg); } // Install serializer service with default configuration - http_proto::serializer::config cfg; - http_proto::install_serializer_service(rts_ctx, cfg); + http_proto::install_serializer_service(rts_ctx, {}); // Root certificates used for verification ssl_ctx.set_default_verify_paths(); diff --git a/example/client/jsonrpc/cpp20.cpp b/example/client/jsonrpc/cpp20.cpp index 5047884b..5fedc39a 100644 --- a/example/client/jsonrpc/cpp20.cpp +++ b/example/client/jsonrpc/cpp20.cpp @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include @@ -48,16 +50,16 @@ co_main( // Get Ethereum node client software and version std::cout << "web3 client: " - << co_await client[web3_clientVersion]() << '\n'; + << co_await client.async_call(web3_clientVersion) << '\n'; // Get the latest block number - auto block_num = co_await client[eth_blockNumber](); + auto block_num = co_await client.async_call(eth_blockNumber); std::cout << "Block number: " << to_int(block_num) << '\n'; // Get block details - auto block = co_await client[eth_getBlockByNumber]({ block_num, false }); + auto block = co_await client.async_call(eth_getBlockByNumber, { block_num, false }); std::cout<< "Block hash: " << block["hash"] << '\n'; std::cout<< "Block size: " << to_int(block["size"].as_string()) << " Bytes\n"; std::cout<< "Timestamp: " << to_int(block["timestamp"].as_string()) << '\n'; @@ -68,14 +70,16 @@ co_main( auto addr2 = "0x281055afc982d96fab65b3a49cac8b878184cb16"; // Get account balance - auto balance = co_await client[eth_getBalance]({ addr1, block_num }); + auto balance = co_await client.async_call(eth_getBalance, { addr1, block_num }); + std::cout << "Balance: " << std::setprecision(18) << dec_float(to_int(balance)) / dec_float("1e18") << " ETH\n"; // Estimate gas for a transfer - auto gas_estimate = co_await client[eth_estimateGas]( + auto gas_estimate = co_await client.async_call( + eth_estimateGas, { json::object { @@ -89,14 +93,15 @@ co_main( << to_int(gas_estimate) << '\n'; // Get the current gas price - auto gas_price = co_await client[eth_gasPrice](); + auto gas_price = co_await client.async_call(eth_gasPrice); std::cout << "Gas price: " << std::setprecision(3) << dec_float(to_int(gas_price)) / dec_float("1e10") << " GWEI\n"; // Get ETH/USD price from a Chainlink oracle - auto eth_usd = co_await client[eth_call]( + auto eth_usd = co_await client.async_call( + eth_call, { { {"to", "0x5f4ec3df9cbd43714fe2740f5e3616155c5b8419"}, // ETH/USD price feed @@ -148,12 +153,20 @@ main(int, char*[]) { http_proto::response_parser::config cfg; cfg.min_buffer = 64 * 1024; + #ifdef BOOST_RTS_HAS_BROTLI + cfg.apply_brotli_decoder = true; + rts::brotli::install_decode_service(rts_ctx); + #endif + #ifdef BOOST_RTS_HAS_ZLIB + cfg.apply_deflate_decoder = true; + cfg.apply_gzip_decoder = true; + rts::zlib::install_inflate_service(rts_ctx); + #endif http_proto::install_parser_service(rts_ctx, cfg); } // Install serializer service with default configuration - http_proto::serializer::config cfg; - http_proto::install_serializer_service(rts_ctx, cfg); + http_proto::install_serializer_service(rts_ctx, {}); // Root certificates used for verification ssl_ctx.set_default_verify_paths(); diff --git a/example/client/jsonrpc/jsonrpc/client.cpp b/example/client/jsonrpc/jsonrpc/client.cpp index d4d9ccf0..7a87bd27 100644 --- a/example/client/jsonrpc/jsonrpc/client.cpp +++ b/example/client/jsonrpc/jsonrpc/client.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include using namespace boost; @@ -73,7 +76,7 @@ class stream_impl : public any_stream else { asio::async_compose( - shutdown_op{ stream_.next_layer() }, + tcp_shutdown_op{ stream_.next_layer() }, handler, stream_); } @@ -188,32 +191,65 @@ class stream_impl : public any_stream } }; - class shutdown_op + class tcp_shutdown_op { asio::ip::tcp::socket& socket_; - bool init_ = false; public: - shutdown_op(asio::ip::tcp::socket& socket) + tcp_shutdown_op(asio::ip::tcp::socket& socket) : socket_(socket) { } template void - operator()(Self&& self, system::error_code ec = {}) + operator()(Self&& self) { - if(init_) - return self.complete(ec); - init_ = true; - socket_.close(ec); + system::error_code ec; + socket_.shutdown(asio::ip::tcp::socket::shutdown_both, ec); + if(!ec) + socket_.close(ec); asio::async_immediate( socket_.get_executor(), asio::append(std::move(self), ec)); } + + template + void + operator()(Self&& self, system::error_code ec) + { + self.complete(ec); + } }; }; +class json_sink : public http_proto::sink +{ + json::stream_parser& jpr_; + +public: + json_sink(json::stream_parser& jpr) + : jpr_(jpr) + { + } + +private: + results + on_write( + buffers::const_buffer b, + bool more) override + { + results ret; + ret.bytes = jpr_.write( + static_cast(b.data()), + b.size(), + ret.ec); + if(!ret.ec && !more) + jpr_.finish(ret.ec); + return ret; + } +}; + } //namespace // ---------------------------------------------- @@ -278,12 +314,13 @@ class client::request_op http_io::async_read_header( *c_.stream_, c_.pr_, std::move(self)); + c_.pr_.set_body(c_.jpr_); BOOST_ASIO_CORO_YIELD http_io::async_read( *c_.stream_, c_.pr_, std::move(self)); { - auto body = json::parse(c_.pr_.body(), ec); + auto body = c_.jpr_.release(); if(ec || !body.is_object()) return self.complete({ errc::invalid_response }, {}); auto& obj = body.get_object(); @@ -321,16 +358,6 @@ class client::request_op } }; -client:: -invoker_base:: -invoker_base( - client* self, - boost::core::string_view method) - : self_(self) - , method_(method) -{ -} - // ---------------------------------------------- client:: @@ -358,18 +385,27 @@ client( , req_(http_proto::method::post, "/") { using field = http_proto::field; + if(!endpoint_.encoded_target().empty()) req_.set_target(endpoint_.encoded_target()); - req_.set(field::host, endpoint_.encoded_host_and_port().decode()); - req_.set(field::content_type, "application/json"); - req_.set(field::accept, "application/json"); - req_.set(field::user_agent, "Boost.Http.Io"); + + req_.append(field::host, endpoint_.encoded_host_and_port().decode()); + req_.append(field::content_type, "application/json"); + req_.append(field::accept, "application/json"); + req_.append(field::user_agent, "Boost.Http.Io"); + + if(rts_ctx.has_service()) + req_.append(field::accept_encoding, "br"); + + if(rts_ctx.has_service()) + req_.append(field::accept_encoding, "deflate, gzip"); + pr_.reset(); } void client:: -async_request_impl( +async_call_impl( asio::any_completion_handler handler, core::string_view method, json::value params) diff --git a/example/client/jsonrpc/jsonrpc/client.hpp b/example/client/jsonrpc/jsonrpc/client.hpp index f2dca1fb..a61cd3db 100644 --- a/example/client/jsonrpc/jsonrpc/client.hpp +++ b/example/client/jsonrpc/jsonrpc/client.hpp @@ -16,10 +16,13 @@ #include "error.hpp" #include "method.hpp" +#include +#include #include #include #include #include +#include #include #include #include @@ -34,14 +37,8 @@ class client boost::http_proto::serializer sr_; boost::http_proto::response_parser pr_; boost::http_proto::request req_; + boost::json::stream_parser jpr_; std::uint64_t id_ = 0; - struct invoker_base - { - friend client; - client* self_; - boost::core::string_view method_; - invoker_base(client*, boost::core::string_view); - }; public: /// The type of the next layer. @@ -139,162 +136,127 @@ class client this); } - template - class invoker; - /** Call a remote procedure that takes no parameters. - Instances of this type are returned from @ref operator[]. - - @tparam Return The return type of the procedure. - */ - template - class invoker : invoker_base - { - using invoker_base::invoker_base; - public: - - /** Call a remote procedure that takes no parameters. - - The result type depends on the signature of the @ref method object - used to instantiate the invoker. + The result type depends on the signature of the passed @ref method. - @param token The completion token used to produce a completion - handler, which will be invoked when the call completes. - */ - template< - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) - operator()( - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return this->self_->async_request( - this->method_, - {}, - boost::asio::deferred(transform{})) | std::move(token); - } - }; + @param m The @ref method object that contains the name + and signature of the remote procedure. - /** Call a remote procedure with positional parameters (array). - - Instances of this type are returned from @ref operator[]. - - @tparam Return The return type of the procedure. + @param token The completion token used to produce a completion + handler, which will be invoked when the call completes. */ - template - class invoker : invoker_base + template< + typename Return, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) + CompletionToken = boost::asio::deferred_t> + BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) + async_call( + method method, + CompletionToken&& token = {}) { - using invoker_base::invoker_base; - public: + return async_call_impl(method.name, {}, std::move(token)); + } - /** Call a remote procedure with positional parameters (array). + /** Call a remote procedure with positional parameters (array). - The result type depends on the signature of the @ref method object - used to instantiate the invoker. + The result type depends on the signature of the passed @ref method. - @param params A JSON array containing the positional parameters to - use when calling the server method. + @param m The @ref method object that contains the name + and signature of the remote procedure. - @param token The completion token used to produce a completion - handler, which will be invoked when the call completes. - */ - template< - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) - operator()( - boost::json::array params, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return this->self_->async_request( - this->method_, - std::move(params), - boost::asio::deferred(transform{})) | std::move(token); - } - }; + @param params A JSON array containing the positional parameters + to be used when calling the server method. - /** Call a remote procedure with named parameters (object). - - Instances of this type are returned from @ref operator[]. - - @tparam Return The return type of the procedure. + @param token The completion token used to produce a completion + handler, which will be invoked when the call completes. */ - template - class invoker: invoker_base + template< + typename Return, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) + CompletionToken = boost::asio::deferred_t> + BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) + async_call( + method method, + boost::json::array params, + CompletionToken&& token = {}) { - using invoker_base::invoker_base; - public: - - /** Call a remote procedure with named parameters (object). - - The result type depends on the signature of the @ref method object - used to instantiate the invoker. - - @param params A JSON object containing the named parameters to use - when calling the server method. + return async_call_impl( + method.name, std::move(params), std::move(token)); + } - @param token The completion token used to produce a completion - handler, which will be invoked when the call completes. - */ - template< - BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) - CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) - operator()( - boost::json::object params, - CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return this->self_->async_request( - this->method_, - std::move(params), - boost::asio::deferred(transform{})) | std::move(token); - } - }; + /** Call a remote procedure with named parameters (object). - /** Return an @ref invoker instance that can be used to asynchronously - invoke the specified method. + The result type depends on the signature of the passed @ref method. - Example: - @code - client[method_a]({ "param1", "param2" }, completion_token); - @endcode + @param m The @ref method object that contains the name + and signature of the remote procedure. - @return An @ref invoker capable of asynchronously calling the specified - method. + @param params A JSON object containing the named parameters + to be used when calling the server method. - @param m The @ref method object containing the name and signature of the - remote procedure. + @param token The completion token used to produce a completion + handler, which will be invoked when the call completes. */ - template - invoker - operator[](method m) noexcept + template< + typename Return, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error, Return)) + CompletionToken = boost::asio::deferred_t> + BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) + async_call( + method method, + boost::json::object params, + CompletionToken&& token = {}) { - return { this, m.name }; + return async_call_impl( + method.name, std::move(params), std::move(token)); } private: class request_op; template - class transform + class request_and_transform_op { + client& client_; + boost::core::string_view method_; + boost::json::value params_; + public: - boost::asio::deferred_values - operator()(error e, boost::json::value v) + request_and_transform_op( + client& client, + boost::core::string_view method, + boost::json::value params) + : client_(client) + , method_(method) + , params_(std::move(params)) + { + } + + template + void + operator()(Self&& self) + { + client_.async_call_impl( + std::move(self), method_, std::move(params_)); + } + + template + void + operator()(Self&& self, error e, boost::json::value v) { - constexpr auto deferred = boost::asio::deferred; if(e.code()) - return deferred.values(std::move(e), Return{}); + return self.complete(std::move(e), {}); // avoid extra copies when possible if(auto* o = detail::converts_to(v)) - return deferred.values(std::move(e), std::move(*o)); + return self.complete(std::move(e), std::move(*o)); auto o = boost::json::try_value_to(v); if(o.has_error()) - return deferred.values(error(o.error()), Return{}); - return deferred.values(std::move(e), std::move(*o)); + return self.complete(o.error(), {}); + + self.complete(std::move(e), std::move(*o)); } }; @@ -325,51 +287,22 @@ class client } }; - class initiate_async_request : public detail::initiation_base - { - public: - using detail::initiation_base::initiation_base; - - template - void - operator()( - Handler&& handler, - boost::core::string_view method, - boost::json::value params, - client* self) - { - self->async_request_impl( - std::move(handler), method, std::move(params)); - } - }; - - void async_request_impl( + void async_call_impl( boost::asio::any_completion_handler handler, boost::core::string_view method, boost::json::value params); - template - auto - async_request( + template + BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error, Return)) + async_call_impl( boost::core::string_view method, boost::json::value params, CompletionToken&& token) - -> decltype(boost::asio::async_initiate< - CompletionToken, void(error, boost::json::value)>( - initiate_async_request(get_executor()), - token, - method, - std::move(params), - this) - ) { - return boost::asio::async_initiate< - CompletionToken, void(error, boost::json::value)>( - initiate_async_request(get_executor()), - token, - method, - std::move(params), - this); + return boost::asio::async_compose( + request_and_transform_op(*this, method, std::move(params)), + token, + stream_->get_executor()); } std::uint64_t diff --git a/example/client/jsonrpc/jsonrpc/detail/initiation_base.hpp b/example/client/jsonrpc/jsonrpc/detail/initiation_base.hpp index 88f1ecb2..27fb91b2 100644 --- a/example/client/jsonrpc/jsonrpc/detail/initiation_base.hpp +++ b/example/client/jsonrpc/jsonrpc/detail/initiation_base.hpp @@ -25,6 +25,7 @@ struct initiation_base } using executor_type = boost::asio::any_io_executor; + const executor_type& get_executor() const noexcept { diff --git a/example/client/jsonrpc/jsonrpc/errc.cpp b/example/client/jsonrpc/jsonrpc/errc.cpp index 6f8b7e20..0581a73a 100644 --- a/example/client/jsonrpc/jsonrpc/errc.cpp +++ b/example/client/jsonrpc/jsonrpc/errc.cpp @@ -35,8 +35,12 @@ message( { switch (static_cast(code)) { + case errc::version_error: + return "The response object is not JSON-RPC version 2.0"; + case errc::id_mismatch: + return "The response object has a different ID than the request"; case errc::invalid_response: - return "The JSON received is not a valid Response object"; + return "The received body does not contain a valid response object"; case errc::parse_error: return "Invalid JSON was received by the server"; case errc::invalid_request: diff --git a/example/client/jsonrpc/jsonrpc/errc.hpp b/example/client/jsonrpc/jsonrpc/errc.hpp index 73023823..da6120f9 100644 --- a/example/client/jsonrpc/jsonrpc/errc.hpp +++ b/example/client/jsonrpc/jsonrpc/errc.hpp @@ -24,7 +24,7 @@ enum class errc /// The response object has a different ID than the request. id_mismatch, - /// The HTTP body is not a valid response object. + /// The received body does not contain a valid response object. invalid_response, /// Invalid JSON was received by the server. diff --git a/example/client/jsonrpc/jsonrpc/error.hpp b/example/client/jsonrpc/jsonrpc/error.hpp index 84f8f81d..97618a5c 100644 --- a/example/client/jsonrpc/jsonrpc/error.hpp +++ b/example/client/jsonrpc/jsonrpc/error.hpp @@ -20,19 +20,19 @@ namespace jsonrpc { /** An error type that encapsulates both an error code and an optional JSON object containing additional error - details as provided by the server. + information as provided by the server. */ -class error +class error { boost::system::error_code ec_; - boost::json::object object_; + boost::json::object info_; public: error( boost::system::error_code ec, - boost::json::object object = {}) noexcept + boost::json::object info = {}) noexcept : ec_(ec) - , object_(std::move(object)) + , info_(std::move(info)) { } @@ -43,7 +43,7 @@ class error operator=(error&& other) noexcept { ec_ = std::move(other.ec_); - object_ = std::move(other.object_); + info_ = std::move(other.info_); return *this; } @@ -55,12 +55,12 @@ class error } /** Return an optional JSON object containing additional - error details as provided by the server. + error information as provided by the server. */ const boost::json::object& - object() const noexcept + info() const noexcept { - return object_; + return info_; } }; @@ -80,11 +80,11 @@ struct disposition_traits static void throw_exception(const jsonrpc::error& e) { - if(e.object().empty()) + if(e.info().empty()) return BOOST_THROW_EXCEPTION(system::system_error(e.code())); BOOST_THROW_EXCEPTION( - system::system_error(e.code(), json::serialize(e.object()))); + system::system_error(e.code(), json::serialize(e.info()))); } static std::exception_ptr @@ -93,11 +93,11 @@ struct disposition_traits if(!e.code()) return nullptr; - if(e.object().empty()) + if(e.info().empty()) return std::make_exception_ptr(system::system_error(e.code())); return std::make_exception_ptr( - system::system_error(e.code(), json::serialize(e.object()))); + system::system_error(e.code(), json::serialize(e.info()))); } }; } // asio diff --git a/example/client/jsonrpc/jsonrpc/method.hpp b/example/client/jsonrpc/jsonrpc/method.hpp index 3f9bb278..893c93e1 100644 --- a/example/client/jsonrpc/jsonrpc/method.hpp +++ b/example/client/jsonrpc/jsonrpc/method.hpp @@ -14,8 +14,7 @@ namespace jsonrpc { -/** Containin the name and signature of a remote - procedure. +/** Contains the name and signature of a remote procedure. @par Example: @code