diff --git a/nano/rpc/rpc_connection.cpp b/nano/rpc/rpc_connection.cpp index 3b72b4ed..1c27af62 100644 --- a/nano/rpc/rpc_connection.cpp +++ b/nano/rpc/rpc_connection.cpp @@ -54,104 +54,91 @@ void nano::rpc_connection::write_result (std::string body, unsigned version, boo void nano::rpc_connection::read () { auto this_l (shared_from_this ()); - boost::system::error_code header_error; auto header_parser (std::make_shared> ()); - std::promise header_available_promise; - std::future header_available = header_available_promise.get_future (); header_parser->body_limit (rpc_config.max_request_size); - if (!network_constants.is_test_network ()) - { - boost::beast::http::async_read_header (socket, buffer, *header_parser, [this_l, header_parser, &header_available_promise, &header_error](boost::system::error_code const & ec, size_t bytes_transferred) { - size_t header_response_bytes_written = 0; - if (!ec) + boost::beast::http::async_read_header (socket, buffer, *header_parser, [this_l, header_parser](boost::system::error_code const & ec, size_t bytes_transferred) { + if (!ec) + { + if (boost::iequals (header_parser->get ()[boost::beast::http::field::expect], "100-continue")) { - if (boost::iequals (header_parser->get ()[boost::beast::http::field::expect], "100-continue")) + auto continue_response (std::make_shared> ()); + continue_response->version (11); + continue_response->result (boost::beast::http::status::continue_); + continue_response->set (boost::beast::http::field::server, "nano"); + boost::beast::http::async_write (this_l->socket, *continue_response, [this_l, continue_response](boost::system::error_code const & ec, size_t bytes_transferred) {}); + } + + this_l->parse_request (header_parser); + } + else + { + this_l->logger.always_log ("RPC header error: ", ec.message ()); + + // Respond with the reason for the invalid header + auto response_handler ([this_l](std::string const & tree_a) { + this_l->write_result (tree_a, 11); + boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { + this_l->write_completion_handler (this_l); + }); + }); + json_error_response (response_handler, std::string ("Invalid header: ") + ec.message ()); + } + }); +} + +void nano::rpc_connection::parse_request (std::shared_ptr> header_parser) +{ + auto this_l (shared_from_this ()); + auto body_parser (std::make_shared> (std::move (*header_parser))); + boost::beast::http::async_read (socket, buffer, *body_parser, [this_l, body_parser](boost::system::error_code const & ec, size_t bytes_transferred) { + if (!ec) + { + // equivalent to background + this_l->io_ctx.post ([this_l, body_parser]() { + auto & req (body_parser->get ()); + auto start (std::chrono::steady_clock::now ()); + auto version (req.version ()); + std::string request_id (boost::str (boost::format ("%1%") % boost::io::group (std::hex, std::showbase, reinterpret_cast (this_l.get ())))); + auto response_handler ([this_l, version, start, request_id](std::string const & tree_a) { + auto body = tree_a; + this_l->write_result (body, version); + boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { + this_l->write_completion_handler (this_l); + }); + + this_l->logger.always_log (boost::str (boost::format ("RPC request %2% completed in: %1% microseconds") % std::chrono::duration_cast (std::chrono::steady_clock::now () - start).count () % request_id)); + }); + auto method = req.method (); + switch (method) { - boost::beast::http::response continue_response; - continue_response.version (11); - continue_response.result (boost::beast::http::status::continue_); - continue_response.set (boost::beast::http::field::server, "nano"); - auto response_size (boost::beast::http::async_write (this_l->socket, continue_response, boost::asio::use_future)); - header_response_bytes_written = response_size.get (); - } - } - else - { - header_error = ec; - this_l->logger.always_log ("RPC header error: ", ec.message ()); - } - - header_available_promise.set_value (header_response_bytes_written); - }); - - // Await header - header_available.get (); - } - - if (!header_error) - { - auto body_parser (std::make_shared> (std::move (*header_parser))); - boost::beast::http::async_read (socket, buffer, *body_parser, [this_l, body_parser](boost::system::error_code const & ec, size_t bytes_transferred) { - if (!ec) - { - // equivalent to background - this_l->io_ctx.post ([this_l, body_parser]() { - auto & req (body_parser->get ()); - auto start (std::chrono::steady_clock::now ()); - auto version (req.version ()); - std::string request_id (boost::str (boost::format ("%1%") % boost::io::group (std::hex, std::showbase, reinterpret_cast (this_l.get ())))); - auto response_handler ([this_l, version, start, request_id](std::string const & tree_a) { - auto body = tree_a; - this_l->write_result (body, version); + case boost::beast::http::verb::post: + { + auto handler (std::make_shared (this_l->rpc_config, req.body (), request_id, response_handler, this_l->rpc_handler_interface, this_l->logger)); + handler->process_request (); + break; + } + case boost::beast::http::verb::options: + { + this_l->prepare_head (version); + this_l->res.prepare_payload (); boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { this_l->write_completion_handler (this_l); }); - - this_l->logger.always_log (boost::str (boost::format ("RPC request %2% completed in: %1% microseconds") % std::chrono::duration_cast (std::chrono::steady_clock::now () - start).count () % request_id)); - }); - auto method = req.method (); - switch (method) - { - case boost::beast::http::verb::post: - { - auto handler (std::make_shared (this_l->rpc_config, req.body (), request_id, response_handler, this_l->rpc_handler_interface, this_l->logger)); - handler->process_request (); - break; - } - case boost::beast::http::verb::options: - { - this_l->prepare_head (version); - this_l->res.prepare_payload (); - boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { - this_l->write_completion_handler (this_l); - }); - break; - } - default: - { - json_error_response (response_handler, "Can only POST requests"); - break; - } + break; } - }); - } - else - { - this_l->logger.always_log ("RPC read error: ", ec.message ()); - } - }); - } - else - { - // Respond with the reason for the invalid header - auto response_handler ([this_l](std::string const & tree_a) { - this_l->write_result (tree_a, 11); - boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { - this_l->write_completion_handler (this_l); + default: + { + json_error_response (response_handler, "Can only POST requests"); + break; + } + } }); - }); - json_error_response (response_handler, std::string ("Invalid header: ") + header_error.message ()); - } + } + else + { + this_l->logger.always_log ("RPC read error: ", ec.message ()); + } + }); } void nano::rpc_connection::write_completion_handler (std::shared_ptr rpc_connection) diff --git a/nano/rpc/rpc_connection.hpp b/nano/rpc/rpc_connection.hpp index 536f85bf..a9d1b4e4 100644 --- a/nano/rpc/rpc_connection.hpp +++ b/nano/rpc/rpc_connection.hpp @@ -20,6 +20,8 @@ public: virtual void write_completion_handler (std::shared_ptr rpc_connection); void prepare_head (unsigned version, boost::beast::http::status status = boost::beast::http::status::ok); void write_result (std::string body, unsigned version, boost::beast::http::status status = boost::beast::http::status::ok); + void parse_request (std::shared_ptr> header_parser); + void read (); boost::asio::ip::tcp::socket socket;