#ifndef XRPL_SERVER_PLAINHTTPPEER_H_INCLUDED #define XRPL_SERVER_PLAINHTTPPEER_H_INCLUDED #include #include #include #include #include namespace ripple { template class PlainHTTPPeer : public BaseHTTPPeer>, public std::enable_shared_from_this> { private: friend class BaseHTTPPeer; using socket_type = boost::asio::ip::tcp::socket; using stream_type = boost::beast::tcp_stream; using endpoint_type = boost::asio::ip::tcp::endpoint; stream_type stream_; socket_type& socket_; public: template PlainHTTPPeer( Port const& port, Handler& handler, boost::asio::io_context& ioc, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers, stream_type&& stream); void run(); std::shared_ptr websocketUpgrade() override; private: void do_request() override; void do_close() override; }; //------------------------------------------------------------------------------ template template PlainHTTPPeer::PlainHTTPPeer( Port const& port, Handler& handler, boost::asio::io_context& ioc, beast::Journal journal, endpoint_type remote_endpoint, ConstBufferSequence const& buffers, stream_type&& stream) : BaseHTTPPeer( port, handler, ioc.get_executor(), journal, remote_endpoint, buffers) , stream_(std::move(stream)) , socket_(stream_.socket()) { // Set TCP_NODELAY on loopback interfaces, // otherwise Nagle's algorithm makes Env // tests run slower on Linux systems. // if (remote_endpoint.address().is_loopback()) socket_.set_option(boost::asio::ip::tcp::no_delay{true}); } template void PlainHTTPPeer::run() { if (!this->handler_.onAccept(this->session(), this->remote_address_)) { util::spawn( this->strand_, std::bind(&PlainHTTPPeer::do_close, this->shared_from_this())); return; } if (!socket_.is_open()) return; util::spawn( this->strand_, std::bind( &PlainHTTPPeer::do_read, this->shared_from_this(), std::placeholders::_1)); } template std::shared_ptr PlainHTTPPeer::websocketUpgrade() { auto ws = this->ios().template emplace>( this->port_, this->handler_, this->remote_address_, std::move(this->message_), std::move(stream_), this->journal_); return ws; } template void PlainHTTPPeer::do_request() { ++this->request_count_; auto const what = this->handler_.onHandoff( this->session(), std::move(this->message_), this->remote_address_); if (what.moved) return; boost::system::error_code ec; if (what.response) { // half-close on Connection: close if (!what.keep_alive) socket_.shutdown(socket_type::shutdown_receive, ec); if (ec) return this->fail(ec, "request"); return this->write(what.response, what.keep_alive); } // Perform half-close when Connection: close and not SSL if (!beast::rfc2616::is_keep_alive(this->message_)) socket_.shutdown(socket_type::shutdown_receive, ec); if (ec) return this->fail(ec, "request"); // legacy this->handler_.onRequest(this->session()); } template void PlainHTTPPeer::do_close() { boost::system::error_code ec; socket_.shutdown(socket_type::shutdown_send, ec); } } // namespace ripple #endif