diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index 8452e958cf..801636f4ed 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -3302,6 +3302,10 @@ + + True + True + True True @@ -3312,6 +3316,12 @@ + + True + True + + + True True @@ -3324,12 +3334,20 @@ + + + + + + + + @@ -3370,8 +3388,6 @@ - - @@ -3380,10 +3396,6 @@ - - True - True - @@ -3402,42 +3414,16 @@ True True - - True - True - - - True - True - - - - - True - True - - - - - - - - - - - - - diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index 50c1364064..ce0be76f50 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -3762,6 +3762,9 @@ ripple\rpc\impl + + ripple\rpc\impl + ripple\rpc\impl @@ -3771,6 +3774,12 @@ ripple\rpc\impl + + ripple\rpc\impl + + + ripple\rpc\impl + ripple\rpc\impl @@ -3783,15 +3792,27 @@ ripple\rpc\impl + + ripple\rpc\impl + ripple\rpc + + ripple\rpc + ripple\rpc + + ripple\rpc + ripple\rpc + + ripple\rpc + ripple\rpc @@ -3825,9 +3846,6 @@ ripple\rpc\tests - - ripple\server - ripple\server @@ -3840,9 +3858,6 @@ ripple\server\impl - - ripple\server\impl - ripple\server\impl @@ -3864,18 +3879,6 @@ ripple\server\impl - - ripple\server\impl - - - ripple\server\impl - - - ripple\server\impl - - - ripple\server\impl - ripple\server\impl @@ -3885,30 +3888,12 @@ ripple\server\impl - - ripple\server - - - ripple\server - - - ripple\server - ripple\server - - ripple\server - - - ripple\server - ripple\server - - ripple\server - ripple\server diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 068cf3ea43..e777877997 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -67,7 +67,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp index b2e80117bf..e11068c093 100644 --- a/src/ripple/app/main/Main.cpp +++ b/src/ripple/app/main/Main.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 8f28c59db6..0f649e1bad 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -33,11 +33,12 @@ #include #include #include -#include +#include #include #include #include #include +#include #include #include diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp index 8154906faa..6c400dc630 100644 --- a/src/ripple/overlay/impl/OverlayImpl.cpp +++ b/src/ripple/overlay/impl/OverlayImpl.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/ripple/overlay/impl/OverlayImpl.h b/src/ripple/overlay/impl/OverlayImpl.h index a4e572d6c6..6e6adc717d 100644 --- a/src/ripple/overlay/impl/OverlayImpl.h +++ b/src/ripple/overlay/impl/OverlayImpl.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index 98cc79e78d..db773cd407 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/ripple/overlay/make_Overlay.h b/src/ripple/overlay/make_Overlay.h index 4b0eade380..d34c35a665 100644 --- a/src/ripple/overlay/make_Overlay.h +++ b/src/ripple/overlay/make_Overlay.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED #define RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED -#include +#include #include #include #include diff --git a/src/ripple/rpc/Context.h b/src/ripple/rpc/Context.h index ef9f0349ec..4838b995ad 100644 --- a/src/ripple/rpc/Context.h +++ b/src/ripple/rpc/Context.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include diff --git a/src/ripple/server/Role.h b/src/ripple/rpc/Role.h similarity index 100% rename from src/ripple/server/Role.h rename to src/ripple/rpc/Role.h diff --git a/src/ripple/server/make_ServerHandler.h b/src/ripple/rpc/ServerHandler.h similarity index 75% rename from src/ripple/server/make_ServerHandler.h rename to src/ripple/rpc/ServerHandler.h index 8b52d4617a..190205c682 100644 --- a/src/ripple/server/make_ServerHandler.h +++ b/src/ripple/rpc/ServerHandler.h @@ -17,19 +17,30 @@ */ //============================================================================== -#ifndef RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED -#define RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED +#ifndef RIPPLE_RPC_SERVERHANDLER_H_INCLUDED +#define RIPPLE_RPC_SERVERHANDLER_H_INCLUDED +#include +#include #include -#include -#include #include +#include +#include +#include +#include #include +#include #include +#include namespace ripple { -class NetworkOPs; +using ServerHandler = ServerHandlerImp; + +ServerHandler::Setup +setup_ServerHandler ( + Config const& c, + std::ostream& log); std::unique_ptr make_ServerHandler (Application& app, Stoppable& parent, boost::asio::io_service&, diff --git a/src/ripple/rpc/TODO.md b/src/ripple/rpc/TODO.md deleted file mode 100644 index e22c3712d6..0000000000 --- a/src/ripple/rpc/TODO.md +++ /dev/null @@ -1,6 +0,0 @@ -# RPC TODO - -- Redo the interface to actually work correctly for the existing - use-cases that the old code supports. Specifically that RPC commands - can be issued for a particular context like a websocket connection - or other subscriber. diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index 1f55da1b5c..c1a6c5c6c9 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/AccountTxOld.cpp b/src/ripple/rpc/handlers/AccountTxOld.cpp index fb894197cd..d7fa7f5bf3 100644 --- a/src/ripple/rpc/handlers/AccountTxOld.cpp +++ b/src/ripple/rpc/handlers/AccountTxOld.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/LedgerData.cpp b/src/ripple/rpc/handlers/LedgerData.cpp index 90ec8b20d3..56935eff43 100644 --- a/src/ripple/rpc/handlers/LedgerData.cpp +++ b/src/ripple/rpc/handlers/LedgerData.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/LedgerHandler.cpp b/src/ripple/rpc/handlers/LedgerHandler.cpp index 3f6bb8078e..0ab49023e0 100644 --- a/src/ripple/rpc/handlers/LedgerHandler.cpp +++ b/src/ripple/rpc/handlers/LedgerHandler.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include namespace ripple { namespace RPC { diff --git a/src/ripple/rpc/handlers/LedgerHandler.h b/src/ripple/rpc/handlers/LedgerHandler.h index e78096e5f8..e8f6e49801 100644 --- a/src/ripple/rpc/handlers/LedgerHandler.h +++ b/src/ripple/rpc/handlers/LedgerHandler.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace Json { class Object; diff --git a/src/ripple/rpc/handlers/Ping.cpp b/src/ripple/rpc/handlers/Ping.cpp index b1caf97b82..e2fa69fbdd 100644 --- a/src/ripple/rpc/handlers/Ping.cpp +++ b/src/ripple/rpc/handlers/Ping.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index 914fd9298e..21b09abe9d 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/ServerInfo.cpp b/src/ripple/rpc/handlers/ServerInfo.cpp index 7c155f4b15..3478d47f0e 100644 --- a/src/ripple/rpc/handlers/ServerInfo.cpp +++ b/src/ripple/rpc/handlers/ServerInfo.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/ServerState.cpp b/src/ripple/rpc/handlers/ServerState.cpp index e84c45a5c5..730c7d3346 100644 --- a/src/ripple/rpc/handlers/ServerState.cpp +++ b/src/ripple/rpc/handlers/ServerState.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/Subscribe.cpp b/src/ripple/rpc/handlers/Subscribe.cpp index acc64cfe41..dac99ccc10 100644 --- a/src/ripple/rpc/handlers/Subscribe.cpp +++ b/src/ripple/rpc/handlers/Subscribe.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/handlers/TxHistory.cpp b/src/ripple/rpc/handlers/TxHistory.cpp index e7eb9bdd22..cfd9849384 100644 --- a/src/ripple/rpc/handlers/TxHistory.cpp +++ b/src/ripple/rpc/handlers/TxHistory.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include namespace ripple { diff --git a/src/ripple/rpc/handlers/Unsubscribe.cpp b/src/ripple/rpc/handlers/Unsubscribe.cpp index 09402f66cc..58c4cddf57 100644 --- a/src/ripple/rpc/handlers/Unsubscribe.cpp +++ b/src/ripple/rpc/handlers/Unsubscribe.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace ripple { diff --git a/src/ripple/rpc/impl/RPCHandler.cpp b/src/ripple/rpc/impl/RPCHandler.cpp index d8679a32fb..d97fb0feb9 100644 --- a/src/ripple/rpc/impl/RPCHandler.cpp +++ b/src/ripple/rpc/impl/RPCHandler.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include namespace ripple { diff --git a/src/ripple/server/impl/Role.cpp b/src/ripple/rpc/impl/Role.cpp similarity index 99% rename from src/ripple/server/impl/Role.cpp rename to src/ripple/rpc/impl/Role.cpp index cb136f586d..c40f885fb7 100644 --- a/src/ripple/server/impl/Role.cpp +++ b/src/ripple/rpc/impl/Role.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include namespace ripple { diff --git a/src/ripple/server/impl/ServerHandlerImp.cpp b/src/ripple/rpc/impl/ServerHandlerImp.cpp similarity index 98% rename from src/ripple/server/impl/ServerHandlerImp.cpp rename to src/ripple/rpc/impl/ServerHandlerImp.cpp index 6083d38520..c180f95a9d 100644 --- a/src/ripple/server/impl/ServerHandlerImp.cpp +++ b/src/ripple/rpc/impl/ServerHandlerImp.cpp @@ -23,17 +23,17 @@ #include #include #include -#include -#include +#include +#include +#include #include -#include +#include #include #include #include #include #include #include -#include #include #include #include @@ -50,18 +50,11 @@ namespace ripple { -ServerHandler::ServerHandler (Stoppable& parent) - : Stoppable ("ServerHandler", parent) -{ -} - -//------------------------------------------------------------------------------ - ServerHandlerImp::ServerHandlerImp (Application& app, Stoppable& parent, boost::asio::io_service& io_service, JobQueue& jobQueue, NetworkOPs& networkOPs, Resource::Manager& resourceManager, CollectorManager& cm) - : ServerHandler (parent) + : Stoppable("ServerHandler", parent) , app_ (app) , m_resourceManager (resourceManager) , m_journal (app_.journal("Server")) diff --git a/src/ripple/server/impl/ServerHandlerImp.h b/src/ripple/rpc/impl/ServerHandlerImp.h similarity index 61% rename from src/ripple/server/impl/ServerHandlerImp.h rename to src/ripple/rpc/impl/ServerHandlerImp.h index 1f45d6f1c6..de33b8b153 100644 --- a/src/ripple/server/impl/ServerHandlerImp.h +++ b/src/ripple/rpc/impl/ServerHandlerImp.h @@ -17,22 +17,20 @@ */ //============================================================================== -#ifndef RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED -#define RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED +#ifndef RIPPLE_RPC_SERVERHANDLERIMP_H_INCLUDED +#define RIPPLE_RPC_SERVERHANDLERIMP_H_INCLUDED #include #include -#include -#include -#include -#include -#include +#include +#include #include #include #include #include #include #include +#include namespace ripple { @@ -42,69 +40,42 @@ bool operator< (Port const& lhs, Port const& rhs) return lhs.name < rhs.name; } -class WSInfoSub : public InfoSub -{ - std::weak_ptr ws_; - std::string user_; - std::string fwdfor_; - -public: - WSInfoSub(Source& source, - std::shared_ptr const& ws) - : InfoSub(source) - , ws_(ws) - { - auto const& h = ws->request().headers; - auto it = h.find("X-User"); - if (it != h.end() && - isIdentified( - ws->port(), beast::IPAddressConversion::from_asio( - ws->remote_endpoint()).address(), it->second)) - { - user_ = it->second; - it = h.find("X-Forwarded-For"); - if (it != h.end()) - fwdfor_ = it->second; - } - } - - std::string - user() const - { - return user_; - } - - std::string - forwarded_for() const - { - return fwdfor_; - } - - void - send(Json::Value const& jv, bool) - { - auto sp = ws_.lock(); - if(! sp) - return; - beast::streambuf sb; - stream(jv, - [&](void const* data, std::size_t n) - { - sb.commit(boost::asio::buffer_copy( - sb.prepare(n), boost::asio::buffer(data, n))); - }); - auto m = std::make_shared< - StreambufWSMsg>( - std::move(sb)); - sp->send(m); - } -}; - -// Private implementation class ServerHandlerImp - : public ServerHandler - , public Handler + : public Stoppable { +public: + struct Setup + { + std::vector ports; + + // Memberspace + struct client_t + { + bool secure = false; + std::string ip; + std::uint16_t port = 0; + std::string user; + std::string password; + std::string admin_user; + std::string admin_password; + }; + + // Configuration when acting in client role + client_t client; + + // Configuration for the Overlay + struct overlay_t + { + boost::asio::ip::address ip; + std::uint16_t port = 0; + }; + + overlay_t overlay; + + void + makeContexts(); + }; + private: Application& app_; @@ -128,14 +99,13 @@ public: ~ServerHandlerImp(); -private: using Output = Json::Output; void - setup (Setup const& setup, beast::Journal journal) override; + setup (Setup const& setup, beast::Journal journal); Setup const& - setup() const override + setup() const { return setup_; } @@ -145,7 +115,7 @@ private: // void - onStop() override; + onStop(); // // Handler @@ -153,31 +123,31 @@ private: bool onAccept (Session& session, - boost::asio::ip::tcp::endpoint endpoint) override; + boost::asio::ip::tcp::endpoint endpoint); Handoff onHandoff (Session& session, std::unique_ptr && bundle, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override; + boost::asio::ip::tcp::endpoint remote_address); Handoff onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override; + boost::asio::ip::tcp::endpoint remote_address); void - onRequest (Session& session) override; + onRequest (Session& session); void onWSMessage(std::shared_ptr session, - std::vector const& buffers) override; + std::vector const& buffers); void onClose (Session& session, - boost::system::error_code const&) override; + boost::system::error_code const&); void - onStopped (Server&) override; + onStopped (Server&); //-------------------------------------------------------------------------- diff --git a/src/ripple/rpc/impl/TransactionSign.h b/src/ripple/rpc/impl/TransactionSign.h index 484bdb3258..d3f14989ee 100644 --- a/src/ripple/rpc/impl/TransactionSign.h +++ b/src/ripple/rpc/impl/TransactionSign.h @@ -21,7 +21,7 @@ #define RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED #include -#include +#include #include namespace ripple { diff --git a/src/ripple/rpc/impl/WSInfoSub.h b/src/ripple/rpc/impl/WSInfoSub.h new file mode 100644 index 0000000000..c7f8848914 --- /dev/null +++ b/src/ripple/rpc/impl/WSInfoSub.h @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_RPC_WSINFOSUB_H +#define RIPPLE_RPC_WSINFOSUB_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { + +class WSInfoSub : public InfoSub +{ + std::weak_ptr ws_; + std::string user_; + std::string fwdfor_; + +public: + WSInfoSub(Source& source, std::shared_ptr const& ws) + : InfoSub(source) + , ws_(ws) + { + auto const& h = ws->request().headers; + auto it = h.find("X-User"); + if (it != h.end() && + isIdentified( + ws->port(), beast::IPAddressConversion::from_asio( + ws->remote_endpoint()).address(), it->second)) + { + user_ = it->second; + it = h.find("X-Forwarded-For"); + if (it != h.end()) + fwdfor_ = it->second; + } + } + + std::string + user() const + { + return user_; + } + + std::string + forwarded_for() const + { + return fwdfor_; + } + + void + send(Json::Value const& jv, bool) + { + auto sp = ws_.lock(); + if(! sp) + return; + beast::streambuf sb; + stream(jv, + [&](void const* data, std::size_t n) + { + sb.commit(boost::asio::buffer_copy( + sb.prepare(n), boost::asio::buffer(data, n))); + }); + auto m = std::make_shared< + StreambufWSMsg>( + std::move(sb)); + sp->send(m); + } +}; + +} // ripple + +#endif diff --git a/src/ripple/server/json_body.h b/src/ripple/rpc/json_body.h similarity index 96% rename from src/ripple/server/json_body.h rename to src/ripple/rpc/json_body.h index 0f794587bb..0ecad3dcf8 100644 --- a/src/ripple/server/json_body.h +++ b/src/ripple/rpc/json_body.h @@ -17,8 +17,8 @@ */ //============================================================================== -#ifndef RIPPLE_SERVER_JSON_BODY_H -#define RIPPLE_SERVER_JSON_BODY_H +#ifndef RIPPLE_RPC_JSON_BODY_H +#define RIPPLE_RPC_JSON_BODY_H #include #include diff --git a/src/ripple/server/Handler.h b/src/ripple/server/Handler.h deleted file mode 100644 index f258a107f3..0000000000 --- a/src/ripple/server/Handler.h +++ /dev/null @@ -1,105 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_SERVER_HANDLER_H_INCLUDED -#define RIPPLE_SERVER_HANDLER_H_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -class Session; -class Server; - -/** Processes all sessions. - Thread safety: - Must be safe to call concurrently from any number of foreign threads. -*/ -struct Handler -{ - /** Called when a connection is accepted. - @return `true` If we should keep the connection. - */ - virtual - bool - onAccept (Session& session, - boost::asio::ip::tcp::endpoint remote_address) = 0; - - /** Called to process a complete HTTP request. - The handler can do one of three things: - - Ignore the request (return default constructed What) - - Return a response (by setting response in the What) - - Take ownership of the socket by using rvalue move - and setting moved = `true` in the What. - If the handler ignores the request, the legacy onRequest - is called. - */ - /** @{ */ - virtual - Handoff - onHandoff (Session& session, - std::unique_ptr && bundle, - http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) = 0; - - virtual - Handoff - onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket, - http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) = 0; - /** @} */ - - /** Called when we have a complete HTTP request. */ - // VFALCO TODO Pass the message as a template arg - virtual void onRequest (Session& session) = 0; - - /** Called when the session ends. - Guaranteed to be called once. - @param errorCode Non zero for a failed connection. - */ - virtual void onClose (Session& session, - boost::system::error_code const& ec) = 0; - - /** Called when the server has finished its stop. */ - virtual void onStopped (Server& server) = 0; - - // - // WebSockets - // - - /** Called on a WebSocket Upgrade request. */ - - - /** Called for each complete WebSocket message. */ - virtual - void - onWSMessage(std::shared_ptr session, - std::vector const& buffers) = 0; - -}; - -} // ripple - -#endif diff --git a/src/ripple/server/README.md b/src/ripple/server/README.md deleted file mode 100644 index fb0bbaeed4..0000000000 --- a/src/ripple/server/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Server - -This contains the HTTP Server and ServerHandler diff --git a/src/ripple/server/Server.h b/src/ripple/server/Server.h index fc52298c76..46ede02c1b 100644 --- a/src/ripple/server/Server.h +++ b/src/ripple/server/Server.h @@ -21,51 +21,22 @@ #define RIPPLE_SERVER_SERVER_H_INCLUDED #include +#include #include #include +#include namespace ripple { -/** A multi-protocol server. - - This server maintains multiple configured listening ports, - with each listening port allows for multiple protocols including - HTTP, HTTP/S, WebSocket, Secure WebSocket, and the Peer protocol. -*/ -class Server +/** Create the HTTP server using the specified handler. */ +template +std::unique_ptr +make_Server(Handler& handler, + boost::asio::io_service& io_service, beast::Journal journal) { -public: - /** Destroy the server. - The server is closed if it is not already closed. This call - blocks until the server has stopped. - */ - virtual - ~Server() = default; - - /** Returns the Journal associated with the server. */ - virtual - beast::Journal - journal() = 0; - - /** Set the listening port settings. - This may only be called once. - */ - virtual - void - ports (std::vector const& v) = 0; - - /** Close the server. - The close is performed asynchronously. The handler will be notified - when the server has stopped. The server is considered stopped when - there are no pending I/O completion handlers and all connections - have closed. - Thread safety: - Safe to call concurrently from any thread. - */ - virtual - void - close() = 0; -}; + return std::make_unique>( + handler, io_service, journal); +} } // ripple diff --git a/src/ripple/server/ServerHandler.h b/src/ripple/server/ServerHandler.h deleted file mode 100644 index d787108a59..0000000000 --- a/src/ripple/server/ServerHandler.h +++ /dev/null @@ -1,98 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_SERVER_SERVERHANDLER_H_INCLUDED -#define RIPPLE_SERVER_SERVERHANDLER_H_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -class ServerHandler : public Stoppable -{ -protected: - ServerHandler (Stoppable& parent); - -public: - struct Setup - { - std::vector ports; - - // Memberspace - struct client_t - { - bool secure = false; - std::string ip; - std::uint16_t port = 0; - std::string user; - std::string password; - std::string admin_user; - std::string admin_password; - }; - - // Configuration when acting in client role - client_t client; - - // Configuration for the Overlay - struct overlay_t - { - boost::asio::ip::address ip; - std::uint16_t port = 0; - }; - - overlay_t overlay; - - void - makeContexts(); - }; - - virtual - ~ServerHandler() = default; - - /** Opens listening ports based on the Config settings - This is implemented outside the constructor to support - two-stage initialization in the Application object. - */ - virtual - void - setup (Setup const& setup, beast::Journal journal) = 0; - - /** Returns the setup associated with the handler. */ - virtual - Setup const& - setup() const = 0; -}; - -//------------------------------------------------------------------------------ - -ServerHandler::Setup -setup_ServerHandler ( - Config const& c, - std::ostream& log); - -} // ripple - -#endif diff --git a/src/ripple/server/WSSession.h b/src/ripple/server/WSSession.h index 52b2322024..254d86d643 100644 --- a/src/ripple/server/WSSession.h +++ b/src/ripple/server/WSSession.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_SERVER_WSSESSION_H_INCLUDED #define RIPPLE_SERVER_WSSESSION_H_INCLUDED +#include #include #include #include diff --git a/src/ripple/server/impl/BaseHTTPPeer.h b/src/ripple/server/impl/BaseHTTPPeer.h index 42ed4f9b69..16fd319b4d 100644 --- a/src/ripple/server/impl/BaseHTTPPeer.h +++ b/src/ripple/server/impl/BaseHTTPPeer.h @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. + Copyright(c) 2012, 2013 Ripple Labs Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -22,9 +22,7 @@ #include #include -#include #include -#include #include #include #include // for is_short_read? @@ -48,7 +46,7 @@ namespace ripple { /** Represents an active connection. */ -template +template class BaseHTTPPeer : public io_list::work , public Session @@ -71,12 +69,12 @@ protected: struct buffer { - buffer (void const* ptr, std::size_t len) - : data (new char[len]) - , bytes (len) - , used (0) + buffer(void const* ptr, std::size_t len) + : data(new char[len]) + , bytes(len) + , used(0) { - memcpy (data.get(), ptr, len); + memcpy(data.get(), ptr, len); } std::unique_ptr data; @@ -111,8 +109,8 @@ protected: //-------------------------------------------------------------------------- public: - template - BaseHTTPPeer (Port const& port, Handler& handler, + template + BaseHTTPPeer(Port const& port, Handler& handler, boost::asio::io_service& io_service, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers); @@ -135,7 +133,7 @@ protected: } void - fail (error_code ec, char const* what); + fail(error_code ec, char const* what); void start_timer(); @@ -144,18 +142,18 @@ protected: cancel_timer(); void - on_timer (error_code ec); + on_timer(error_code ec); void - do_read (yield_context yield); + do_read(yield_context do_yield); void on_write(error_code const& ec, std::size_t bytes_transferred); void - do_writer (std::shared_ptr const& writer, - bool keep_alive, yield_context yield); + do_writer(std::shared_ptr const& writer, + bool keep_alive, yield_context do_yield); virtual void @@ -192,10 +190,10 @@ protected: } void - write (void const* buffer, std::size_t bytes) override; + write(void const* buffer, std::size_t bytes) override; void - write (std::shared_ptr const& writer, + write(std::shared_ptr const& writer, bool keep_alive) override; std::shared_ptr @@ -205,27 +203,28 @@ protected: complete() override; void - close (bool graceful) override; + close(bool graceful) override; }; //------------------------------------------------------------------------------ -template -template -BaseHTTPPeer::BaseHTTPPeer (Port const& port, Handler& handler, +template +template +BaseHTTPPeer:: +BaseHTTPPeer(Port const& port, Handler& handler, boost::asio::io_service& io_service, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers) : port_(port) , handler_(handler) - , work_ (io_service) - , strand_ (io_service) - , timer_ (io_service) - , remote_address_ (remote_address) - , journal_ (journal) + , work_(io_service) + , strand_(io_service) + , timer_(io_service) + , remote_address_(remote_address) + , journal_(journal) { - read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare ( - boost::asio::buffer_size (buffers)), buffers)); + read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare( + boost::asio::buffer_size(buffers)), buffers)); static std::atomic sid; nid_ = ++sid; id_ = std::string("#") + std::to_string(nid_) + " "; @@ -233,22 +232,24 @@ BaseHTTPPeer::BaseHTTPPeer (Port const& port, Handler& handler, "accept: " << remote_address_.address(); } -template -BaseHTTPPeer::~BaseHTTPPeer() +template +BaseHTTPPeer:: +~BaseHTTPPeer() { handler_.onClose(session(), ec_); JLOG(journal_.trace()) << id_ << "destroyed: " << request_count_ << - ((request_count_ == 1) ? " request" : " requests"); + ((request_count_ == 1) ? " request" : " requests"); } -template +template void -BaseHTTPPeer::close() +BaseHTTPPeer:: +close() { - if (! strand_.running_in_this_thread()) + if(! strand_.running_in_this_thread()) return strand_.post(std::bind( - (void(BaseHTTPPeer::*)(void))&BaseHTTPPeer::close, + (void(BaseHTTPPeer::*)(void))&BaseHTTPPeer::close, impl().shared_from_this())); error_code ec; impl().stream_.lowest_layer().close(ec); @@ -256,64 +257,69 @@ BaseHTTPPeer::close() //------------------------------------------------------------------------------ -template +template void -BaseHTTPPeer::fail (error_code ec, char const* what) +BaseHTTPPeer:: +fail(error_code ec, char const* what) { - if (! ec_ && ec != boost::asio::error::operation_aborted) + if(! ec_ && ec != boost::asio::error::operation_aborted) { ec_ = ec; JLOG(journal_.trace()) << id_ << std::string(what) << ": " << ec.message(); - impl().stream_.lowest_layer().close (ec); + impl().stream_.lowest_layer().close(ec); } } -template +template void -BaseHTTPPeer::start_timer() +BaseHTTPPeer:: +start_timer() { error_code ec; - timer_.expires_from_now (std::chrono::seconds(timeoutSeconds), ec); - if (ec) - return fail (ec, "start_timer"); - timer_.async_wait (strand_.wrap (std::bind ( - &BaseHTTPPeer::on_timer, impl().shared_from_this(), + timer_.expires_from_now(std::chrono::seconds(timeoutSeconds), ec); + if(ec) + return fail(ec, "start_timer"); + timer_.async_wait(strand_.wrap(std::bind( + &BaseHTTPPeer::on_timer, impl().shared_from_this(), beast::asio::placeholders::error))); } // Convenience for discarding the error code -template +template void -BaseHTTPPeer::cancel_timer() +BaseHTTPPeer:: +cancel_timer() { error_code ec; timer_.cancel(ec); } // Called when session times out -template +template void -BaseHTTPPeer::on_timer (error_code ec) +BaseHTTPPeer:: +on_timer(error_code ec) { - if (ec == boost::asio::error::operation_aborted) + if(ec == boost::asio::error::operation_aborted) return; - if (! ec) - ec = boost::system::errc::make_error_code ( + if(! ec) + ec = boost::system::errc::make_error_code( boost::system::errc::timed_out); - fail (ec, "timer"); + fail(ec, "timer"); } //------------------------------------------------------------------------------ -template +template void -BaseHTTPPeer::do_read (yield_context yield) +BaseHTTPPeer:: +do_read(yield_context do_yield) { complete_ = false; error_code ec; beast::http::async_read(impl().stream_, - read_buf_, message_, yield[ec]); + read_buf_, message_, do_yield[ec]); // VFALCO What if the connection was closed? cancel_timer(); do_request(); @@ -321,9 +327,10 @@ BaseHTTPPeer::do_read (yield_context yield) // Send everything in the write queue. // The write queue must not be empty upon entry. -template +template void -BaseHTTPPeer::on_write(error_code const& ec, +BaseHTTPPeer:: +on_write(error_code const& ec, std::size_t bytes_transferred) { cancel_timer(); @@ -349,19 +356,20 @@ BaseHTTPPeer::on_write(error_code const& ec, impl().shared_from_this(), placeholders::error, placeholders::bytes_transferred))); } - if (! complete_) + if(! complete_) return; - if (graceful_) + if(graceful_) return do_close(); boost::asio::spawn(strand_, - std::bind (&BaseHTTPPeer::do_read, + std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } -template +template void -BaseHTTPPeer::do_writer (std::shared_ptr const& writer, - bool keep_alive, yield_context yield) +BaseHTTPPeer:: +do_writer(std::shared_ptr const& writer, + bool keep_alive, yield_context do_yield) { std::function resume; { @@ -369,43 +377,44 @@ BaseHTTPPeer::do_writer (std::shared_ptr const& writer, resume = std::function ( [this, p, writer, keep_alive]() { - boost::asio::spawn (strand_, std::bind ( - &BaseHTTPPeer::do_writer, p, writer, keep_alive, + boost::asio::spawn(strand_, std::bind( + &BaseHTTPPeer::do_writer, p, writer, keep_alive, std::placeholders::_1)); }); } for(;;) { - if (! writer->prepare (bufferSize, resume)) + if(! writer->prepare(bufferSize, resume)) return; error_code ec; - auto const bytes_transferred = boost::asio::async_write ( + auto const bytes_transferred = boost::asio::async_write( impl().stream_, writer->data(), boost::asio::transfer_at_least(1), - yield[ec]); - if (ec) - return fail (ec, "writer"); + do_yield[ec]); + if(ec) + return fail(ec, "writer"); writer->consume(bytes_transferred); - if (writer->complete()) + if(writer->complete()) break; } - if (! keep_alive) + if(! keep_alive) return do_close(); - boost::asio::spawn (strand_, std::bind (&BaseHTTPPeer::do_read, + boost::asio::spawn(strand_, std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } //------------------------------------------------------------------------------ // Send a copy of the data. -template +template void -BaseHTTPPeer::write( +BaseHTTPPeer:: +write( void const* buffer, std::size_t bytes) { - if (bytes == 0) + if(bytes == 0) return; if([&] { @@ -414,7 +423,7 @@ BaseHTTPPeer::write( return wq_.size() == 1 && wq2_.size() == 0; }()) { - if (strand_.running_in_this_thread()) + if(strand_.running_in_this_thread()) return strand_.post(std::bind( &BaseHTTPPeer::on_write, impl().shared_from_this(), @@ -424,33 +433,36 @@ BaseHTTPPeer::write( } } -template +template void -BaseHTTPPeer::write (std::shared_ptr const& writer, +BaseHTTPPeer:: +write(std::shared_ptr const& writer, bool keep_alive) { - boost::asio::spawn (strand_, std::bind ( - &BaseHTTPPeer::do_writer, impl().shared_from_this(), + boost::asio::spawn(strand_, std::bind( + &BaseHTTPPeer::do_writer, impl().shared_from_this(), writer, keep_alive, std::placeholders::_1)); } // DEPRECATED // Make the Session asynchronous -template +template std::shared_ptr -BaseHTTPPeer::detach() +BaseHTTPPeer:: +detach() { return impl().shared_from_this(); } // DEPRECATED -// Called to indicate the response has been written (but not sent) -template +// Called to indicate the response has been written(but not sent) +template void -BaseHTTPPeer::complete() +BaseHTTPPeer:: +complete() { - if (! strand_.running_in_this_thread()) - return strand_.post(std::bind (&BaseHTTPPeer::complete, + if(! strand_.running_in_this_thread()) + return strand_.post(std::bind(&BaseHTTPPeer::complete, impl().shared_from_this())); message_ = {}; @@ -458,40 +470,41 @@ BaseHTTPPeer::complete() { std::lock_guard lock(mutex_); - if (! wq_.empty() && ! wq2_.empty()) + if(! wq_.empty() && ! wq2_.empty()) return; } // keep-alive - boost::asio::spawn (strand_, std::bind (&BaseHTTPPeer::do_read, + boost::asio::spawn(strand_, std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } // DEPRECATED // Called from the Handler to close the session. -template +template void -BaseHTTPPeer::close (bool graceful) +BaseHTTPPeer:: +close(bool graceful) { - if (! strand_.running_in_this_thread()) + if(! strand_.running_in_this_thread()) return strand_.post(std::bind( - (void(BaseHTTPPeer::*)(bool))&BaseHTTPPeer::close, + (void(BaseHTTPPeer::*)(bool))&BaseHTTPPeer::close, impl().shared_from_this(), graceful)); complete_ = true; - if (graceful) + if(graceful) { graceful_ = true; { std::lock_guard lock(mutex_); - if (! wq_.empty() || ! wq2_.empty()) + if(! wq_.empty() || ! wq2_.empty()) return; } return do_close(); } error_code ec; - impl().stream_.lowest_layer().close (ec); + impl().stream_.lowest_layer().close(ec); } } // ripple diff --git a/src/ripple/server/impl/BasePeer.h b/src/ripple/server/impl/BasePeer.h index b8ee642be6..77874949cd 100644 --- a/src/ripple/server/impl/BasePeer.h +++ b/src/ripple/server/impl/BasePeer.h @@ -20,7 +20,6 @@ #ifndef RIPPLE_SERVER_BASEPEER_H_INCLUDED #define RIPPLE_SERVER_BASEPEER_H_INCLUDED -#include #include #include #include @@ -32,7 +31,7 @@ namespace ripple { // Common part of all peers -template +template class BasePeer : public io_list::work { @@ -76,8 +75,9 @@ private: //------------------------------------------------------------------------------ -template -BasePeer::BasePeer(Port const& port, Handler& handler, +template +BasePeer:: +BasePeer(Port const& port, Handler& handler, endpoint_type remote_address, boost::asio::io_service& io_service, beast::Journal journal) @@ -96,9 +96,10 @@ BasePeer::BasePeer(Port const& port, Handler& handler, { } -template +template void -BasePeer::close() +BasePeer:: +close() { if (! strand_.running_in_this_thread()) return strand_.post(std::bind( @@ -107,10 +108,11 @@ BasePeer::close() impl().ws_.lowest_layer().close(ec); } -template +template template void -BasePeer::fail(error_code ec, String const& what) +BasePeer:: +fail(error_code ec, String const& what) { assert(strand_.running_in_this_thread()); if(! ec_ && diff --git a/src/ripple/server/impl/BaseWSPeer.h b/src/ripple/server/impl/BaseWSPeer.h index a4cb52ab98..0a32d8a595 100644 --- a/src/ripple/server/impl/BaseWSPeer.h +++ b/src/ripple/server/impl/BaseWSPeer.h @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. + Copyright(c) 2012, 2013 Ripple Labs Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -30,9 +30,9 @@ namespace ripple { /** Represents an active WebSocket connection. */ -template +template class BaseWSPeer - : public BasePeer + : public BasePeer , public WSSession { protected: @@ -40,8 +40,8 @@ protected: using error_code = boost::system::error_code; using endpoint_type = boost::asio::ip::tcp::endpoint; using waitable_timer = boost::asio::basic_waitable_timer ; - using BasePeer::fail; - using BasePeer::strand_; + using BasePeer::fail; + using BasePeer::strand_; enum { @@ -50,7 +50,7 @@ protected: }; private: - friend class BasePeer; + friend class BasePeer; http_request_type request_; beast::websocket::opcode op_; @@ -168,25 +168,27 @@ protected: //------------------------------------------------------------------------------ -template +template template -BaseWSPeer::BaseWSPeer( +BaseWSPeer:: +BaseWSPeer( Port const& port, Handler& handler, endpoint_type remote_address, beast::http::request_v1&& request, boost::asio::io_service& io_service, beast::Journal journal) - : BasePeer(port, handler, remote_address, + : BasePeer(port, handler, remote_address, io_service, journal) , request_(std::move(request)) , timer_(io_service) { } -template +template void -BaseWSPeer::run() +BaseWSPeer:: +run() { if(! strand_.running_in_this_thread()) return strand_.post(std::bind( @@ -198,9 +200,10 @@ BaseWSPeer::run() placeholders::error))); } -template +template void -BaseWSPeer::send(std::shared_ptr w) +BaseWSPeer:: +send(std::shared_ptr w) { // Maximum send queue size static std::size_t constexpr limit = 100; @@ -208,7 +211,7 @@ BaseWSPeer::send(std::shared_ptr w) return strand_.post(std::bind( &BaseWSPeer::send, impl().shared_from_this(), std::move(w))); - if (wq_.size() >= limit) + if(wq_.size() >= limit) { cr_.code = static_cast(4000); cr_.reason = "Client is too slow."; @@ -221,9 +224,10 @@ BaseWSPeer::send(std::shared_ptr w) on_write({}); } -template +template void -BaseWSPeer::close() +BaseWSPeer:: +close() { if(! strand_.running_in_this_thread()) return strand_.post(std::bind( @@ -236,28 +240,31 @@ BaseWSPeer::close() beast::asio::placeholders::error))); } -template +template void -BaseWSPeer::complete() +BaseWSPeer:: +complete() { - if (! strand_.running_in_this_thread()) + if(! strand_.running_in_this_thread()) return strand_.post(std::bind( &BaseWSPeer::complete, impl().shared_from_this())); do_read(); } -template +template void -BaseWSPeer::on_write_sb(error_code const& ec) +BaseWSPeer:: +on_write_sb(error_code const& ec) { if(ec) return fail(ec, "write_resp"); do_read(); } -template +template void -BaseWSPeer::do_write() +BaseWSPeer:: +do_write() { if(! strand_.running_in_this_thread()) return strand_.post(std::bind( @@ -265,9 +272,10 @@ BaseWSPeer::do_write() on_write({}); } -template +template void -BaseWSPeer::on_write(error_code const& ec) +BaseWSPeer:: +on_write(error_code const& ec) { cancel_timer(); if(ec) @@ -292,9 +300,10 @@ BaseWSPeer::on_write(error_code const& ec) placeholders::error))); } -template +template void -BaseWSPeer::on_write_fin(error_code const& ec) +BaseWSPeer:: +on_write_fin(error_code const& ec) { if(ec) return fail(ec, "write_fin"); @@ -307,9 +316,10 @@ BaseWSPeer::on_write_fin(error_code const& ec) on_write({}); } -template +template void -BaseWSPeer::do_read() +BaseWSPeer:: +do_read() { if(! strand_.running_in_this_thread()) return strand_.post(std::bind( @@ -321,9 +331,10 @@ BaseWSPeer::do_read() cancel_timer(); } -template +template void -BaseWSPeer::on_read(error_code const& ec) +BaseWSPeer:: +on_read(error_code const& ec) { if(ec == beast::websocket::error::closed) return do_close(); @@ -338,48 +349,52 @@ BaseWSPeer::on_read(error_code const& ec) rb_.consume(rb_.size()); } -template +template void -BaseWSPeer::on_close(error_code const& ec) +BaseWSPeer:: +on_close(error_code const& ec) { // great } -template +template void -BaseWSPeer::start_timer() +BaseWSPeer:: +start_timer() { // Max seconds without completing a message static constexpr std::chrono::seconds timeout{30}; error_code ec; - timer_.expires_from_now (timeout, ec); - if (ec) - return fail (ec, "start_timer"); - timer_.async_wait (strand_.wrap (std::bind ( - &BaseWSPeer::on_timer, impl().shared_from_this(), + timer_.expires_from_now(timeout, ec); + if(ec) + return fail(ec, "start_timer"); + timer_.async_wait(strand_.wrap(std::bind( + &BaseWSPeer::on_timer, impl().shared_from_this(), beast::asio::placeholders::error))); } // Convenience for discarding the error code -template +template void -BaseWSPeer::cancel_timer() +BaseWSPeer:: +cancel_timer() { error_code ec; timer_.cancel(ec); } // Called when session times out -template +template void -BaseWSPeer::on_timer (error_code ec) +BaseWSPeer:: +on_timer(error_code ec) { - if (ec == boost::asio::error::operation_aborted) + if(ec == boost::asio::error::operation_aborted) return; - if (! ec) - ec = boost::system::errc::make_error_code ( + if(! ec) + ec = boost::system::errc::make_error_code( boost::system::errc::timed_out); - fail (ec, "timer"); + fail(ec, "timer"); } } // ripple diff --git a/src/ripple/server/impl/Door.cpp b/src/ripple/server/impl/Door.cpp deleted file mode 100644 index 19c4b2acf4..0000000000 --- a/src/ripple/server/impl/Door.cpp +++ /dev/null @@ -1,296 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -/** Detect SSL client handshakes. - Analyzes the bytes in the provided buffer to detect the SSL client - handshake. If the buffer contains insufficient data, more data will be - read from the stream until there is enough to determine a result. - No bytes are discarded from buf. Any additional bytes read are retained. - buf must provide an interface compatible with boost::asio::streambuf - http://boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/streambuf.html - See - http://www.ietf.org/rfc/rfc2246.txt - Section 7.4. Handshake protocol - @param socket The stream to read from - @param buf A buffer to hold the received data - @param yield A yield context - @return The error code if an error occurs, otherwise `true` if - the data read indicates the SSL client handshake. -*/ -template -std::pair -detect_ssl (Socket& socket, StreamBuf& buf, Yield yield) -{ - std::pair result; - result.second = false; - for(;;) - { - std::size_t const max = 4; // the most bytes we could need - unsigned char data[max]; - auto const bytes = boost::asio::buffer_copy ( - boost::asio::buffer(data), buf.data()); - - if (bytes > 0) - { - if (data[0] != 0x16) // message type 0x16 = "SSL Handshake" - break; - } - - if (bytes >= max) - { - result.second = true; - break; - } - - buf.commit(boost::asio::async_read (socket, - buf.prepare(max - bytes), boost::asio::transfer_at_least(1), - yield[result.first])); - if (result.first) - break; - } - return result; -} - -//------------------------------------------------------------------------------ - -Door::Detector::Detector(Port const& port, - Handler& handler, socket_type&& socket, - endpoint_type remote_address, beast::Journal j) - : port_(port) - , handler_(handler) - , socket_(std::move(socket)) - , timer_(socket_.get_io_service()) - , remote_address_(remote_address) - , strand_(socket_.get_io_service()) - , j_(j) -{ -} - -void -Door::Detector::run() -{ - // do_detect must be called before do_timer or else - // the timer can be canceled before it gets set. - boost::asio::spawn (strand_, std::bind (&Detector::do_detect, - shared_from_this(), std::placeholders::_1)); - - boost::asio::spawn (strand_, std::bind (&Detector::do_timer, - shared_from_this(), std::placeholders::_1)); -} - -void -Door::Detector::close() -{ - error_code ec; - socket_.close(ec); - timer_.cancel(ec); -} - -void -Door::Detector::do_timer (yield_context yield) -{ - error_code ec; // ignored - while (socket_.is_open()) - { - timer_.async_wait (yield[ec]); - if (timer_.expires_from_now() <= std::chrono::seconds(0)) - socket_.close(ec); - } -} - -void -Door::Detector::do_detect (boost::asio::yield_context yield) -{ - bool ssl; - error_code ec; - beast::streambuf buf(16); - timer_.expires_from_now(std::chrono::seconds(15)); - std::tie(ec, ssl) = detect_ssl(socket_, buf, yield); - error_code unused; - timer_.cancel(unused); - if (! ec) - { - if (ssl) - { - if(auto sp = ios().emplace(port_, handler_, - j_, remote_address_, buf.data(), - std::move(socket_))) - sp->run(); - return; - } - if(auto sp = ios().emplace(port_, handler_, - j_, remote_address_, buf.data(), - std::move(socket_))) - sp->run(); - return; - } - if (ec != boost::asio::error::operation_aborted) - { - JLOG(j_.trace()) << - "Error detecting ssl: " << ec.message() << - " from " << remote_address_; - } -} - -//------------------------------------------------------------------------------ - -Door::Door (Handler& handler, boost::asio::io_service& io_service, - Port const& port, beast::Journal j) - : j_(j) - , port_(port) - , handler_(handler) - , acceptor_(io_service) - , strand_(io_service) - , ssl_( - port_.protocol.count("https") > 0 || - //port_.protocol.count("wss") > 0 || - port_.protocol.count("wss2") > 0 || - port_.protocol.count("peer") > 0) - , plain_( - port_.protocol.count("http") > 0 || - //port_.protocol.count("ws") > 0 || - port_.protocol.count("ws2")) -{ - error_code ec; - endpoint_type const local_address = - endpoint_type(port.ip, port.port); - - acceptor_.open(local_address.protocol(), ec); - if (ec) - { - JLOG(j_.error()) << - "Open port '" << port.name << "' failed:" << ec.message(); - Throw (); - } - - acceptor_.set_option( - boost::asio::ip::tcp::acceptor::reuse_address(true), ec); - if (ec) - { - JLOG(j_.error()) << - "Option for port '" << port.name << "' failed:" << ec.message(); - Throw (); - } - - acceptor_.bind(local_address, ec); - if (ec) - { - JLOG(j_.error()) << - "Bind port '" << port.name << "' failed:" << ec.message(); - Throw (); - } - - acceptor_.listen(boost::asio::socket_base::max_connections, ec); - if (ec) - { - JLOG(j_.error()) << - "Listen on port '" << port.name << "' failed:" << ec.message(); - Throw (); - } - - JLOG(j_.info()) << - "Opened " << port; -} - -void -Door::run() -{ - boost::asio::spawn (strand_, std::bind(&Door::do_accept, - shared_from_this(), std::placeholders::_1)); -} - -void -Door::close() -{ - if (! strand_.running_in_this_thread()) - return strand_.post(std::bind( - &Door::close, shared_from_this())); - error_code ec; - acceptor_.close(ec); -} - -//------------------------------------------------------------------------------ - -template -void -Door::create (bool ssl, ConstBufferSequence const& buffers, - socket_type&& socket, endpoint_type remote_address) -{ - if (ssl) - { - if(auto sp = ios().emplace(port_, handler_, - j_, remote_address, buffers, - std::move(socket))) - sp->run(); - return; - } - if(auto sp = ios().emplace(port_, handler_, - j_, remote_address, buffers, - std::move(socket))) - sp->run(); -} - -void -Door::do_accept (boost::asio::yield_context yield) -{ - for(;;) - { - error_code ec; - endpoint_type remote_address; - socket_type socket (acceptor_.get_io_service()); - acceptor_.async_accept (socket, remote_address, yield[ec]); - if (ec && ec != boost::asio::error::operation_aborted) - { - JLOG(j_.error()) << - "accept: " << ec.message(); - } - if (ec == boost::asio::error::operation_aborted) - break; - if (ec) - continue; - - if (ssl_ && plain_) - { - if(auto sp = ios().emplace(port_, - handler_, std::move(socket), remote_address, - j_)) - sp->run(); - } - else if (ssl_ || plain_) - { - create(ssl_, boost::asio::null_buffers{}, - std::move(socket), remote_address); - } - } -} - -} // ripple diff --git a/src/ripple/server/impl/Door.h b/src/ripple/server/impl/Door.h index 7f36fd5670..c5fcb0bc48 100644 --- a/src/ripple/server/impl/Door.h +++ b/src/ripple/server/impl/Door.h @@ -21,24 +21,32 @@ #define RIPPLE_SERVER_DOOR_H_INCLUDED #include -#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include #include #include #include +#include #include #include namespace ripple { /** A listening socket. */ +template class Door : public io_list::work - , public std::enable_shared_from_this + , public std::enable_shared_from_this> { private: using clock_type = std::chrono::steady_clock; @@ -107,6 +115,287 @@ private: void do_accept (yield_context yield); }; +/** Detect SSL client handshakes. + Analyzes the bytes in the provided buffer to detect the SSL client + handshake. If the buffer contains insufficient data, more data will be + read from the stream until there is enough to determine a result. + No bytes are discarded from buf. Any additional bytes read are retained. + buf must provide an interface compatible with boost::asio::streambuf + http://boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/streambuf.html + See + http://www.ietf.org/rfc/rfc2246.txt + Section 7.4. Handshake protocol + @param socket The stream to read from + @param buf A buffer to hold the received data + @param do_yield A do_yield context + @return The error code if an error occurs, otherwise `true` if + the data read indicates the SSL client handshake. +*/ +template +std::pair +detect_ssl (Socket& socket, StreamBuf& buf, Yield do_yield) +{ + std::pair result; + result.second = false; + for(;;) + { + std::size_t const max = 4; // the most bytes we could need + unsigned char data[max]; + auto const bytes = boost::asio::buffer_copy ( + boost::asio::buffer(data), buf.data()); + + if (bytes > 0) + { + if (data[0] != 0x16) // message type 0x16 = "SSL Handshake" + break; + } + + if (bytes >= max) + { + result.second = true; + break; + } + + buf.commit(boost::asio::async_read (socket, + buf.prepare(max - bytes), boost::asio::transfer_at_least(1), + do_yield[result.first])); + if (result.first) + break; + } + return result; +} + +template +Door::Detector:: +Detector(Port const& port, + Handler& handler, socket_type&& socket, + endpoint_type remote_address, beast::Journal j) + : port_(port) + , handler_(handler) + , socket_(std::move(socket)) + , timer_(socket_.get_io_service()) + , remote_address_(remote_address) + , strand_(socket_.get_io_service()) + , j_(j) +{ +} + +template +void +Door::Detector:: +run() +{ + // do_detect must be called before do_timer or else + // the timer can be canceled before it gets set. + boost::asio::spawn(strand_, std::bind (&Detector::do_detect, + this->shared_from_this(), std::placeholders::_1)); + + boost::asio::spawn(strand_, std::bind (&Detector::do_timer, + this->shared_from_this(), std::placeholders::_1)); +} + +template +void +Door::Detector:: +close() +{ + error_code ec; + socket_.close(ec); + timer_.cancel(ec); +} + +template +void +Door::Detector:: +do_timer(yield_context do_yield) +{ + error_code ec; // ignored + while (socket_.is_open()) + { + timer_.async_wait (do_yield[ec]); + if (timer_.expires_from_now() <= std::chrono::seconds(0)) + socket_.close(ec); + } +} + +template +void +Door::Detector:: +do_detect(boost::asio::yield_context do_yield) +{ + bool ssl; + error_code ec; + beast::streambuf buf(16); + timer_.expires_from_now(std::chrono::seconds(15)); + std::tie(ec, ssl) = detect_ssl(socket_, buf, do_yield); + error_code unused; + timer_.cancel(unused); + if (! ec) + { + if (ssl) + { + if(auto sp = ios().template emplace>( + port_, handler_, j_, remote_address_, + buf.data(), std::move(socket_))) + sp->run(); + return; + } + if(auto sp = ios().template emplace>( + port_, handler_, j_, remote_address_, + buf.data(), std::move(socket_))) + sp->run(); + return; + } + if (ec != boost::asio::error::operation_aborted) + { + JLOG(j_.trace()) << + "Error detecting ssl: " << ec.message() << + " from " << remote_address_; + } +} + +//------------------------------------------------------------------------------ + +template +Door:: +Door(Handler& handler, boost::asio::io_service& io_service, + Port const& port, beast::Journal j) + : j_(j) + , port_(port) + , handler_(handler) + , acceptor_(io_service) + , strand_(io_service) + , ssl_( + port_.protocol.count("https") > 0 || + //port_.protocol.count("wss") > 0 || + port_.protocol.count("wss2") > 0 || + port_.protocol.count("peer") > 0) + , plain_( + port_.protocol.count("http") > 0 || + //port_.protocol.count("ws") > 0 || + port_.protocol.count("ws2")) +{ + error_code ec; + endpoint_type const local_address = + endpoint_type(port.ip, port.port); + + acceptor_.open(local_address.protocol(), ec); + if (ec) + { + JLOG(j_.error()) << + "Open port '" << port.name << "' failed:" << ec.message(); + Throw (); + } + + acceptor_.set_option( + boost::asio::ip::tcp::acceptor::reuse_address(true), ec); + if (ec) + { + JLOG(j_.error()) << + "Option for port '" << port.name << "' failed:" << ec.message(); + Throw (); + } + + acceptor_.bind(local_address, ec); + if (ec) + { + JLOG(j_.error()) << + "Bind port '" << port.name << "' failed:" << ec.message(); + Throw (); + } + + acceptor_.listen(boost::asio::socket_base::max_connections, ec); + if (ec) + { + JLOG(j_.error()) << + "Listen on port '" << port.name << "' failed:" << ec.message(); + Throw (); + } + + JLOG(j_.info()) << + "Opened " << port; +} + +template +void +Door:: +run() +{ + boost::asio::spawn(strand_, std::bind(&Door::do_accept, + this->shared_from_this(), std::placeholders::_1)); +} + +template +void +Door:: +close() +{ + if (! strand_.running_in_this_thread()) + return strand_.post(std::bind( + &Door::close, this->shared_from_this())); + error_code ec; + acceptor_.close(ec); +} + +//------------------------------------------------------------------------------ + +template +template +void +Door:: +create(bool ssl, ConstBufferSequence const& buffers, + socket_type&& socket, endpoint_type remote_address) +{ + if (ssl) + { + if(auto sp = ios().template emplace>( + port_, handler_, j_, remote_address, + buffers, std::move(socket))) + sp->run(); + return; + } + if(auto sp = ios().template emplace>( + port_, handler_, j_, remote_address, + buffers, std::move(socket))) + sp->run(); +} + +template +void +Door:: +do_accept(boost::asio::yield_context do_yield) +{ + for(;;) + { + error_code ec; + endpoint_type remote_address; + socket_type socket (acceptor_.get_io_service()); + acceptor_.async_accept (socket, remote_address, do_yield[ec]); + if (ec && ec != boost::asio::error::operation_aborted) + { + JLOG(j_.error()) << + "accept: " << ec.message(); + } + if (ec == boost::asio::error::operation_aborted) + break; + if (ec) + continue; + + if (ssl_ && plain_) + { + if(auto sp = ios().template emplace( + port_, handler_, std::move(socket), + remote_address, j_)) + sp->run(); + } + else if (ssl_ || plain_) + { + create(ssl_, boost::asio::null_buffers{}, + std::move(socket), remote_address); + } + } +} + } // ripple #endif diff --git a/src/ripple/server/impl/PlainHTTPPeer.h b/src/ripple/server/impl/PlainHTTPPeer.h index f3165e4592..ec3e34579d 100644 --- a/src/ripple/server/impl/PlainHTTPPeer.h +++ b/src/ripple/server/impl/PlainHTTPPeer.h @@ -26,19 +26,21 @@ namespace ripple { +template class PlainHTTPPeer - : public BaseHTTPPeer - , public std::enable_shared_from_this + : public BaseHTTPPeer> + , public std::enable_shared_from_this> { private: - friend class BaseHTTPPeer; + friend class BaseHTTPPeer; using socket_type = boost::asio::ip::tcp::socket; + using endpoint_type = boost::asio::ip::tcp::endpoint; socket_type stream_; public: - template - PlainHTTPPeer (Port const& port, Handler& handler, + template + PlainHTTPPeer(Port const& port, Handler& handler, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers, socket_type&& socket); @@ -58,12 +60,14 @@ private: //------------------------------------------------------------------------------ -template -PlainHTTPPeer::PlainHTTPPeer (Port const& port, Handler& handler, +template +template +PlainHTTPPeer:: +PlainHTTPPeer(Port const& port, Handler& handler, beast::Journal journal, endpoint_type remote_endpoint, ConstBufferSequence const& buffers, socket_type&& socket) - : BaseHTTPPeer(port, handler, socket.get_io_service(), - journal, remote_endpoint, buffers) + : BaseHTTPPeer(port, handler, + socket.get_io_service(), journal, remote_endpoint, buffers) , stream_(std::move(socket)) { // Set TCP_NODELAY on loopback interfaces, @@ -74,67 +78,75 @@ PlainHTTPPeer::PlainHTTPPeer (Port const& port, Handler& handler, stream_.set_option(boost::asio::ip::tcp::no_delay{true}); } +template void -PlainHTTPPeer::run() +PlainHTTPPeer:: +run() { - if (!handler_.onAccept (session(), remote_address_)) + if (! this->handler_.onAccept(this->session(), this->remote_address_)) { - boost::asio::spawn (strand_, + boost::asio::spawn(this->strand_, std::bind (&PlainHTTPPeer::do_close, - shared_from_this())); + this->shared_from_this())); return; } if (! stream_.is_open()) return; - boost::asio::spawn (strand_, std::bind (&PlainHTTPPeer::do_read, - shared_from_this(), std::placeholders::_1)); + boost::asio::spawn(this->strand_, std::bind(&PlainHTTPPeer::do_read, + this->shared_from_this(), std::placeholders::_1)); } +template std::shared_ptr -PlainHTTPPeer::websocketUpgrade() +PlainHTTPPeer:: +websocketUpgrade() { - auto ws = ios().emplace( - port_, handler_, remote_address_, - std::move(message_), std::move(stream_), - journal_); + 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() +PlainHTTPPeer:: +do_request() { - ++request_count_; - auto const what = handler_.onHandoff (session(), - std::move(stream_), std::move(message_), remote_address_); + ++this->request_count_; + auto const what = this->handler_.onHandoff(this->session(), + std::move(stream_), std::move(this->message_), this->remote_address_); if (what.moved) return; - error_code ec; + boost::system::error_code ec; if (what.response) { // half-close on Connection: close if (! what.keep_alive) - stream_.shutdown (socket_type::shutdown_receive, ec); + stream_.shutdown(socket_type::shutdown_receive, ec); if (ec) - return fail (ec, "request"); - return write(what.response, what.keep_alive); + return this->fail(ec, "request"); + return this->write(what.response, what.keep_alive); } // Perform half-close when Connection: close and not SSL - if (! is_keep_alive(message_)) - stream_.shutdown (socket_type::shutdown_receive, ec); + if (! is_keep_alive(this->message_)) + stream_.shutdown(socket_type::shutdown_receive, ec); if (ec) - return fail (ec, "request"); + return this->fail(ec, "request"); // legacy - handler_.onRequest (session()); + this->handler_.onRequest(this->session()); } +template void -PlainHTTPPeer::do_close() +PlainHTTPPeer:: +do_close() { - error_code ec; - stream_.shutdown (socket_type::shutdown_send, ec); + boost::system::error_code ec; + stream_.shutdown(socket_type::shutdown_send, ec); } } // ripple diff --git a/src/ripple/server/impl/PlainWSPeer.h b/src/ripple/server/impl/PlainWSPeer.h index 7e1de8c250..73e32de2bb 100644 --- a/src/ripple/server/impl/PlainWSPeer.h +++ b/src/ripple/server/impl/PlainWSPeer.h @@ -25,13 +25,14 @@ namespace ripple { +template class PlainWSPeer - : public BaseWSPeer - , public std::enable_shared_from_this + : public BaseWSPeer> + , public std::enable_shared_from_this> { private: - friend class BasePeer; - friend class BaseWSPeer; + friend class BasePeer; + friend class BaseWSPeer; using clock_type = std::chrono::system_clock; using error_code = boost::system::error_code; @@ -58,28 +59,32 @@ private: //------------------------------------------------------------------------------ +template template -PlainWSPeer::PlainWSPeer( +PlainWSPeer:: +PlainWSPeer( Port const& port, Handler& handler, endpoint_type remote_address, beast::http::request_v1&& request, socket_type&& socket, beast::Journal journal) - : BaseWSPeer(port, handler, remote_address, std::move(request), - socket.get_io_service(), journal) + : BaseWSPeer(port, handler, remote_address, + std::move(request), socket.get_io_service(), journal) , ws_(std::move(socket)) { } +template void -PlainWSPeer::do_close() +PlainWSPeer:: +do_close() { error_code ec; auto& sock = ws_.next_layer(); sock.shutdown(socket_type::shutdown_both, ec); if(ec) - return fail(ec, "do_close"); + return this->fail(ec, "do_close"); } } // ripple diff --git a/src/ripple/server/impl/SSLHTTPPeer.h b/src/ripple/server/impl/SSLHTTPPeer.h index 5a1a37be33..847f00b47f 100644 --- a/src/ripple/server/impl/SSLHTTPPeer.h +++ b/src/ripple/server/impl/SSLHTTPPeer.h @@ -27,21 +27,25 @@ namespace ripple { +template class SSLHTTPPeer - : public BaseHTTPPeer - , public std::enable_shared_from_this + : public BaseHTTPPeer> + , public std::enable_shared_from_this> { private: - friend class BaseHTTPPeer; + friend class BaseHTTPPeer; using socket_type = boost::asio::ip::tcp::socket; using stream_type = boost::asio::ssl::stream ; + using endpoint_type = boost::asio::ip::tcp::endpoint; + using yield_context = boost::asio::yield_context; + using error_code = boost::system::error_code; std::unique_ptr ssl_bundle_; stream_type& stream_; public: - template - SSLHTTPPeer (Port const& port, Handler& handler, + template + SSLHTTPPeer(Port const& port, Handler& handler, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers, socket_type&& socket); @@ -53,7 +57,7 @@ public: private: void - do_handshake (yield_context yield); + do_handshake(yield_context do_yield); void do_request() override; @@ -62,16 +66,19 @@ private: do_close() override; void - on_shutdown (error_code ec); + on_shutdown(error_code ec); }; //------------------------------------------------------------------------------ -template -SSLHTTPPeer::SSLHTTPPeer (Port const& port, Handler& handler, +template +template +SSLHTTPPeer:: +SSLHTTPPeer(Port const& port, Handler& handler, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const& buffers, socket_type&& socket) - : BaseHTTPPeer (port, handler, socket.get_io_service(), journal, remote_address, buffers) + : BaseHTTPPeer(port, handler, + socket.get_io_service(), journal, remote_address, buffers) , ssl_bundle_(std::make_unique( port.context, std::move(socket))) , stream_(ssl_bundle_->stream) @@ -79,86 +86,99 @@ SSLHTTPPeer::SSLHTTPPeer (Port const& port, Handler& handler, } // Called when the acceptor accepts our socket. +template void -SSLHTTPPeer::run() +SSLHTTPPeer:: +run() { - if (!handler_.onAccept (session(), remote_address_)) + if(! this->handler_.onAccept(this->session(), this->remote_address_)) { - boost::asio::spawn (strand_, - std::bind (&SSLHTTPPeer::do_close, - shared_from_this())); + boost::asio::spawn(this->strand_, + std::bind(&SSLHTTPPeer::do_close, + this->shared_from_this())); return; } - if (! stream_.lowest_layer().is_open()) return; - - boost::asio::spawn (strand_, std::bind (&SSLHTTPPeer::do_handshake, - shared_from_this(), std::placeholders::_1)); + boost::asio::spawn(this->strand_, std::bind( + &SSLHTTPPeer::do_handshake, this->shared_from_this(), + std::placeholders::_1)); } +template std::shared_ptr -SSLHTTPPeer::websocketUpgrade() +SSLHTTPPeer:: +websocketUpgrade() { - auto ws = ios().emplace( - port_, handler_, remote_address_, - std::move(message_), std::move(ssl_bundle_), - journal_); + auto ws = this->ios().template emplace>( + this->port_, this->handler_, this->remote_address_, + std::move(this->message_), std::move(this->ssl_bundle_), + this->journal_); return ws; } +template void -SSLHTTPPeer::do_handshake (yield_context yield) +SSLHTTPPeer:: +do_handshake(yield_context do_yield) { - error_code ec; - stream_.set_verify_mode (boost::asio::ssl::verify_none); - start_timer(); - read_buf_.consume(stream_.async_handshake( - stream_type::server, read_buf_.data(), yield[ec])); - cancel_timer(); + boost::system::error_code ec; + stream_.set_verify_mode(boost::asio::ssl::verify_none); + this->start_timer(); + this->read_buf_.consume(stream_.async_handshake( + stream_type::server, this->read_buf_.data(), do_yield[ec])); + this->cancel_timer(); if (ec) - return fail(ec, "handshake"); + return this->fail(ec, "handshake"); bool const http = - port().protocol.count("peer") > 0 || + this->port().protocol.count("peer") > 0 || //port().protocol.count("wss") > 0 || - port().protocol.count("wss2") > 0 || - port().protocol.count("https") > 0; - if (http) + this->port().protocol.count("wss2") > 0 || + this->port().protocol.count("https") > 0; + if(http) { - boost::asio::spawn (strand_, std::bind (&SSLHTTPPeer::do_read, - shared_from_this(), std::placeholders::_1)); + boost::asio::spawn(this->strand_, + std::bind(&SSLHTTPPeer::do_read, + this->shared_from_this(), std::placeholders::_1)); return; } - // this will be destroyed + // `this` will be destroyed } +template void -SSLHTTPPeer::do_request() +SSLHTTPPeer:: +do_request() { - ++request_count_; - auto const what = handler_.onHandoff (session(), - std::move(ssl_bundle_), std::move(message_), remote_address_); - if (what.moved) + ++this->request_count_; + auto const what = this->handler_.onHandoff(this->session(), + std::move(ssl_bundle_), std::move(this->message_), + this->remote_address_); + if(what.moved) return; - if (what.response) - return write(what.response, what.keep_alive); + if(what.response) + return this->write(what.response, what.keep_alive); // legacy - handler_.onRequest (session()); + this->handler_.onRequest(this->session()); } +template void -SSLHTTPPeer::do_close() +SSLHTTPPeer:: +do_close() { - start_timer(); - stream_.async_shutdown (strand_.wrap (std::bind ( - &SSLHTTPPeer::on_shutdown, shared_from_this(), + this->start_timer(); + stream_.async_shutdown(this->strand_.wrap(std::bind ( + &SSLHTTPPeer::on_shutdown, this->shared_from_this(), std::placeholders::_1))); } +template void -SSLHTTPPeer::on_shutdown (error_code ec) +SSLHTTPPeer:: +on_shutdown(error_code ec) { - cancel_timer(); + this->cancel_timer(); stream_.lowest_layer().close(ec); } diff --git a/src/ripple/server/impl/SSLWSPeer.h b/src/ripple/server/impl/SSLWSPeer.h index 5e57644ac6..99341c07af 100644 --- a/src/ripple/server/impl/SSLWSPeer.h +++ b/src/ripple/server/impl/SSLWSPeer.h @@ -29,13 +29,14 @@ namespace ripple { +template class SSLWSPeer - : public BaseWSPeer - , public std::enable_shared_from_this + : public BaseWSPeer> + , public std::enable_shared_from_this> { private: - friend class BasePeer; - friend class BaseWSPeer; + friend class BasePeer; + friend class BaseWSPeer; using clock_type = std::chrono::system_clock; using error_code = boost::system::error_code; @@ -68,8 +69,10 @@ private: //------------------------------------------------------------------------------ +template template -SSLWSPeer::SSLWSPeer( +SSLWSPeer:: +SSLWSPeer( Port const& port, Handler& handler, endpoint_type remote_endpoint, @@ -77,25 +80,30 @@ SSLWSPeer::SSLWSPeer( std::unique_ptr< beast::asio::ssl_bundle>&& ssl_bundle, beast::Journal journal) - : BaseWSPeer(port, handler, remote_endpoint, std::move(request), - ssl_bundle->socket.get_io_service(), journal) + : BaseWSPeer(port, handler, + remote_endpoint, std::move(request), + ssl_bundle->socket.get_io_service(), journal) , ssl_bundle_(std::move(ssl_bundle)) , ws_(ssl_bundle_->stream) { } +template void -SSLWSPeer::do_close() +SSLWSPeer:: +do_close() { //start_timer(); using namespace beast::asio; ws_.next_layer().async_shutdown( - strand_.wrap(std::bind(&SSLWSPeer::on_shutdown, - shared_from_this(), placeholders::error))); + this->strand_.wrap(std::bind(&SSLWSPeer::on_shutdown, + this->shared_from_this(), placeholders::error))); } +template void -SSLWSPeer::on_shutdown(error_code ec) +SSLWSPeer:: +on_shutdown(error_code ec) { //cancel_timer(); ws_.lowest_layer().close(ec); diff --git a/src/ripple/server/impl/ServerImpl.cpp b/src/ripple/server/impl/ServerImpl.cpp deleted file mode 100644 index 326c68d53d..0000000000 --- a/src/ripple/server/impl/ServerImpl.cpp +++ /dev/null @@ -1,101 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -ServerImpl::ServerImpl (Handler& handler, - boost::asio::io_service& io_service, beast::Journal journal) - : handler_(handler) - , j_(journal) - , io_service_(io_service) - , strand_(io_service_) - , work_(io_service_) -{ -} - -ServerImpl::~ServerImpl() -{ - // Handler::onStopped will not be called - work_ = boost::none; - ios_.close(); - ios_.join(); -} - -void -ServerImpl::ports (std::vector const& ports) -{ - if (closed()) - Throw ("ports() on closed Server"); - ports_.reserve(ports.size()); - for(auto const& port : ports) - { - if (! port.websockets()) - { - ports_.push_back(port); - if(auto sp = ios_.emplace(handler_, - io_service_, ports_.back(), j_)) - { - list_.push_back(sp); - sp->run(); - } - } - } -} - -void -ServerImpl::close() -{ - ios_.close( - [&] - { - work_ = boost::none; - handler_.onStopped(*this); - }); -} - -bool -ServerImpl::closed() -{ - return ios_.closed(); -} - -//-------------------------------------------------------------------------- - -std::unique_ptr -make_Server (Handler& handler, - boost::asio::io_service& io_service, beast::Journal journal) -{ - return std::make_unique(handler, io_service, journal); -} - -} // ripple diff --git a/src/ripple/server/impl/ServerImpl.h b/src/ripple/server/impl/ServerImpl.h index 3177592899..f78c94e0cd 100644 --- a/src/ripple/server/impl/ServerImpl.h +++ b/src/ripple/server/impl/ServerImpl.h @@ -21,8 +21,8 @@ #define RIPPLE_SERVER_SERVERIMPL_H_INCLUDED #include -#include #include +#include #include #include #include @@ -30,17 +30,52 @@ #include #include #include -#include -#include -#include #include -#include namespace ripple { -class BasicPeer; -class Door; +/** A multi-protocol server. + This server maintains multiple configured listening ports, + with each listening port allows for multiple protocols including + HTTP, HTTP/S, WebSocket, Secure WebSocket, and the Peer protocol. +*/ +class Server +{ +public: + /** Destroy the server. + The server is closed if it is not already closed. This call + blocks until the server has stopped. + */ + virtual + ~Server() = default; + + /** Returns the Journal associated with the server. */ + virtual + beast::Journal + journal() = 0; + + /** Set the listening port settings. + This may only be called once. + */ + virtual + void + ports (std::vector const& v) = 0; + + /** Close the server. + The close is performed asynchronously. The handler will be notified + when the server has stopped. The server is considered stopped when + there are no pending I/O completion handlers and all connections + have closed. + Thread safety: + Safe to call concurrently from any thread. + */ + virtual + void + close() = 0; +}; + +template class ServerImpl : public Server { private: @@ -51,7 +86,7 @@ private: historySize = 100 }; - using Doors = std::vector >; + using Doors = std::vector >>; Handler& handler_; beast::Journal j_; @@ -61,14 +96,14 @@ private: std::mutex m_; std::vector ports_; - std::vector> list_; + std::vector>> list_; int high_ = 0; std::array hist_; io_list ios_; public: - ServerImpl (Handler& handler, + ServerImpl(Handler& handler, boost::asio::io_service& io_service, beast::Journal journal); ~ServerImpl(); @@ -91,7 +126,6 @@ public: return ios_; } -public: boost::asio::io_service& get_io_service() { @@ -107,7 +141,71 @@ private: ceil_log2 (unsigned long long x); }; +template +ServerImpl:: +ServerImpl(Handler& handler, + boost::asio::io_service& io_service, beast::Journal journal) + : handler_(handler) + , j_(journal) + , io_service_(io_service) + , strand_(io_service_) + , work_(io_service_) +{ +} +template +ServerImpl:: +~ServerImpl() +{ + // Handler::onStopped will not be called + work_ = boost::none; + ios_.close(); + ios_.join(); +} + +template +void +ServerImpl:: +ports (std::vector const& ports) +{ + if (closed()) + Throw ("ports() on closed Server"); + ports_.reserve(ports.size()); + for(auto const& port : ports) + { + if (! port.websockets()) + { + ports_.push_back(port); + if(auto sp = ios_.emplace>(handler_, + io_service_, ports_.back(), j_)) + { + list_.push_back(sp); + sp->run(); + } + } + } +} + +template +void +ServerImpl:: +close() +{ + ios_.close( + [&] + { + work_ = boost::none; + handler_.onStopped(*this); + }); +} + +template +bool +ServerImpl:: +closed() +{ + return ios_.closed(); +} } // ripple #endif diff --git a/src/ripple/server/make_Server.h b/src/ripple/server/make_Server.h deleted file mode 100644 index c58e56efe0..0000000000 --- a/src/ripple/server/make_Server.h +++ /dev/null @@ -1,37 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_SERVER_MAKE_SERVER_H_INCLUDED -#define RIPPLE_SERVER_MAKE_SERVER_H_INCLUDED - -#include -#include -#include -#include - -namespace ripple { - -/** Create the HTTP server using the specified handler. */ -std::unique_ptr -make_Server (Handler& handler, - boost::asio::io_service& io_service, beast::Journal journal); - -} // ripple - -#endif diff --git a/src/ripple/server/tests/Server_test.cpp b/src/ripple/server/tests/Server_test.cpp index aa7cbe3759..51aefec995 100644 --- a/src/ripple/server/tests/Server_test.cpp +++ b/src/ripple/server/tests/Server_test.cpp @@ -19,8 +19,6 @@ #include #include -#include -#include #include #include #include @@ -95,11 +93,11 @@ public: //-------------------------------------------------------------------------- - struct TestHandler : Handler + struct TestHandler { bool onAccept (Session& session, - boost::asio::ip::tcp::endpoint endpoint) override + boost::asio::ip::tcp::endpoint endpoint) { return true; } @@ -108,7 +106,7 @@ public: onHandoff (Session& session, std::unique_ptr && bundle, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override + boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } @@ -116,13 +114,13 @@ public: Handoff onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override + boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } void - onRequest (Session& session) override + onRequest (Session& session) { session.write (std::string ("Hello, world!\n")); if (is_keep_alive(session.request())) @@ -133,18 +131,18 @@ public: void onWSMessage(std::shared_ptr session, - std::vector const&) override + std::vector const&) { } void onClose (Session& session, - boost::system::error_code const&) override + boost::system::error_code const&) { } void - onStopped (Server& server) override + onStopped (Server& server) { } }; @@ -303,11 +301,11 @@ public: void stressTest() { - struct NullHandler : Handler + struct NullHandler { bool onAccept (Session& session, - boost::asio::ip::tcp::endpoint endpoint) override + boost::asio::ip::tcp::endpoint endpoint) { return true; } @@ -316,7 +314,7 @@ public: onHandoff (Session& session, std::unique_ptr && bundle, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override + boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } @@ -324,30 +322,30 @@ public: Handoff onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket, http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) override + boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } void - onRequest (Session& session) override + onRequest (Session& session) { } void onWSMessage(std::shared_ptr session, - std::vector const& buffers) override + std::vector const& buffers) { } void onClose (Session& session, - boost::system::error_code const&) override + boost::system::error_code const&) { } void - onStopped (Server& server) override + onStopped (Server& server) { } }; diff --git a/src/ripple/unity/rpcx.cpp b/src/ripple/unity/rpcx.cpp index 4dbf34dfc8..bc652aa6da 100644 --- a/src/ripple/unity/rpcx.cpp +++ b/src/ripple/unity/rpcx.cpp @@ -90,8 +90,10 @@ #include #include -#include +#include #include +#include +#include #include #include diff --git a/src/ripple/unity/server.cpp b/src/ripple/unity/server.cpp index ce5c1c8394..ca74b7de89 100644 --- a/src/ripple/unity/server.cpp +++ b/src/ripple/unity/server.cpp @@ -23,11 +23,7 @@ #include -#include #include #include -#include -#include -#include #include diff --git a/src/ripple/websocket/Connection.h b/src/ripple/websocket/Connection.h index 697efdf15c..696e977a97 100644 --- a/src/ripple/websocket/Connection.h +++ b/src/ripple/websocket/Connection.h @@ -34,10 +34,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include