diff --git a/doc/rippled-example.cfg b/doc/rippled-example.cfg index e92d2ffc5..c29a70619 100644 --- a/doc/rippled-example.cfg +++ b/doc/rippled-example.cfg @@ -14,7 +14,7 @@ # # 4. SMS Gateway # -# 5. Ripple Protcol +# 5. Ripple Protocol # # 6. HTTPS Client # @@ -44,6 +44,41 @@ # or Mac style end of lines. Blank lines and lines beginning with '#' are # ignored. Undefined sections are reserved. No escapes are currently defined. # +# Notation +# +# In this document a simple BNF notation is used. Angle brackets denote +# required elements, square brackets denote optional elements, and single +# quotes indicate string literals. A vertical bar separating 1 or more +# elements is a logical "or"; Any one of the elements may be chosen. +# Parenthesis are notational only, and used to group elements, they are not +# part of the syntax unless they appear in quotes. White space may always +# appear between elements, it has no effect on values. +# +# A required identifier +# '=' The equals sign character +# | Logical "or" +# ( ) Used for grouping +# +# +# An identifier is a string of upper or lower case letters, digits, or +# underscores subject to the requirement that the first character of an +# identifier must be a letter. Identifiers are not case sensitive (but +# values may be). +# +# Some configuration sections contain key/value pairs. A line containing +# a key/value pair has this syntax: +# +# '=' +# +# Depending on the section and key, different value types are possible: +# +# A signed integer +# An unsigned integer +# A boolean. 1 = true/yes/on, 0 = false/no/off. +# +# Consult the documentation on the key in question to determine the possible +# value types. +# # # #------------------------------------------------------------------------------- @@ -193,6 +228,46 @@ # # # +# [overlay] EXPERIMENTAL +# +# This section is EXPERIMENTAL, and should not be +# present for production configuration settings. +# +# A set of key/value pair parameters to configure the overlay. +# +# auto_connect = 0 | 1 +# +# When set, activates the autoconnect feature. This maintains outgoing +# connections using PeerFinder's "Outgoing Connection Strategy." +# +# http_handshake = 0 | 1 +# +# When set, outgoing peer connections will handshaking using a HTTP +# request instead of the legacy TMHello protocol buffers message. +# Incoming peer connections have their handshakes detected automatically. +# +# become_superpeer = 'never' | 'always' | 'auto' +# +# Controls the selection of peer roles: +# +# 'never' Always handshake in the leaf role. +# 'always' Always handshake in the superpeer role. +# 'auto' Start as a leaf, promote to superpeer after +# passing capability check (default). +# +# In the leaf role, a peer does not advertise its IP and port for +# the purpose of receiving incoming connections. The peer also does +# not forward transactions and validations received from other peers. +# +# In the superpeer role, a peer advertises its IP and port for +# receiving incoming connections after passing an incoming connection +# test. Superpeers forward transactions and protocol messages to all +# other peers. Superpeers do not forward validations to other superpeers. +# Instead, a validation received by a superpeer from a leaf is forwarded +# only to other leaf connections. +# +# +# #------------------------------------------------------------------------------- # # 2. Websocket Networking @@ -469,7 +544,7 @@ # # 5. Ripple Protocol # -#------------------ +#------------------- # # These settings affect the behavior of the server instance with respect # to Ripple payment protocol level activities such as validating and diff --git a/src/BeastConfig.h b/src/BeastConfig.h index b175ac334..db4091aa0 100644 --- a/src/BeastConfig.h +++ b/src/BeastConfig.h @@ -208,17 +208,4 @@ #define RIPPLE_SINGLE_IO_SERVICE_THREAD 0 #endif -/** Config: RIPPLE_STRUCTURED_OVERLAY_CLIENT - RIPPLE_STRUCTURED_OVERLAY_SERVER - Enables Structured Overlay support for the client or server roles. - This feature is currently in development: - https://ripplelabs.atlassian.net/browse/RIPD-157 -*/ -#ifndef RIPPLE_STRUCTURED_OVERLAY_CLIENT -#define RIPPLE_STRUCTURED_OVERLAY_CLIENT 0 -#endif -#ifndef RIPPLE_STRUCTURED_OVERLAY_SERVER -#define RIPPLE_STRUCTURED_OVERLAY_SERVER 1 -#endif - #endif diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index ccb9749ed..08e456665 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -193,7 +193,6 @@ public: std::unique_ptr mLedgerDB; std::unique_ptr mWalletDB; - std::unique_ptr m_peerSSLContext; std::unique_ptr m_wsSSLContext; std::unique_ptr m_peers; std::unique_ptr m_rpcDoor; @@ -713,30 +712,18 @@ public: m_treeNodeCache.setTargetSize (getConfig ().getSize (siTreeCacheSize)); m_treeNodeCache.setTargetAge (getConfig ().getSize (siTreeCacheAge)); - //---------------------------------------------------------------------- - // - // - - // SSL context used for Peer connections. - { - m_peerSSLContext.reset (RippleSSLContext::createAnonymous ( - getConfig ().PEER_SSL_CIPHER_LIST)); - - // VFALCO NOTE, It seems the WebSocket context never has - // set_verify_mode called, for either setting of WEBSOCKET_SECURE - m_peerSSLContext->get().set_verify_mode (boost::asio::ssl::verify_none); - } // VFALCO NOTE Unfortunately, in stand-alone mode some code still // foolishly calls overlay(). When this is fixed we can // move the instantiation inside a conditional: // // if (!getConfig ().RUN_STANDALONE) - m_peers = make_Overlay (m_mainIoPool, *m_resourceManager, - *m_siteFiles, getConfig ().getModuleDatabasePath (), - *m_resolver, m_mainIoPool, m_peerSSLContext->get ()); - add (*m_peers); // add to Stoppable + m_peers = make_Overlay (setup_Overlay(getConfig()), m_mainIoPool, + *m_resourceManager, *m_siteFiles, + getConfig().getModuleDatabasePath(), *m_resolver, + m_mainIoPool); + add (*m_peers); // add to PropertyStream // SSL context used for WebSocket connections. if (getConfig ().WEBSOCKET_SECURE) diff --git a/src/ripple/basics/BasicConfig.h b/src/ripple/basics/BasicConfig.h index 8d3e26afa..617374ace 100644 --- a/src/ripple/basics/BasicConfig.h +++ b/src/ripple/basics/BasicConfig.h @@ -39,13 +39,21 @@ using IniFileSections = std::map>; class Section { private: + std::string name_; std::vector lines_; std::vector values_; std::map map_; public: /** Create an empty section. */ - Section() = default; + Section (std::string const& name); + + /** Returns the name of this section. */ + std::string const& + name() const + { + return name_; + } /** Returns the number of key/value pairs. */ std::size_t diff --git a/src/ripple/basics/impl/BasicConfig.cpp b/src/ripple/basics/impl/BasicConfig.cpp index d9830d01f..f286d350d 100644 --- a/src/ripple/basics/impl/BasicConfig.cpp +++ b/src/ripple/basics/impl/BasicConfig.cpp @@ -23,6 +23,11 @@ namespace ripple { +Section::Section (std::string const& name) + : name_(name) +{ +} + void Section::set (std::string const& key, std::string const& value) { @@ -87,13 +92,13 @@ operator<< (std::ostream& os, Section const& section) bool BasicConfig::exists (std::string const& name) const { - return map_.find (name) != map_.end(); + return map_.find(name) != map_.end(); } Section const& BasicConfig::section (std::string const& name) const { - static Section none; + static Section none(""); auto const iter = map_.find (name); if (iter == map_.end()) return none; @@ -111,7 +116,9 @@ BasicConfig::remap (std::string const& legacy_section, return; if (iter->second.lines().size() != 1) return; - auto& s = map_[new_section]; + auto result = map_.emplace(std::piecewise_construct, + std::make_tuple(new_section), std::make_tuple(new_section)); + auto& s = result.first->second; s.append (iter->second.lines().front()); s.set (key, iter->second.lines().front()); } @@ -120,7 +127,8 @@ void BasicConfig::overwrite (std::string const& section, std::string const& key, std::string const& value) { - auto const result = map_.emplace (section, Section{}); + auto const result = map_.emplace (std::piecewise_construct, + std::make_tuple(section), std::make_tuple(section)); result.first->second.set (key, value); } @@ -129,7 +137,8 @@ BasicConfig::build (IniFileSections const& ifs) { for (auto const& entry : ifs) { - auto const result = map_.emplace (entry.first, Section{}); + auto const result = map_.emplace (std::piecewise_construct, + std::make_tuple(entry.first), std::make_tuple(entry.first)); result.first->second.append (entry.second); } } diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h index 364664fc8..142386846 100644 --- a/src/ripple/core/Config.h +++ b/src/ripple/core/Config.h @@ -319,7 +319,6 @@ public: // Peer networking parameters std::string PEER_IP; - std::string PEER_SSL_CIPHER_LIST; bool PEER_PRIVATE; // True to ask peers not to relay current IP. unsigned int PEERS_MAX; diff --git a/src/ripple/core/ConfigSections.h b/src/ripple/core/ConfigSections.h index 610b24520..f0d482124 100644 --- a/src/ripple/core/ConfigSections.h +++ b/src/ripple/core/ConfigSections.h @@ -62,7 +62,6 @@ struct ConfigSection #define SECTION_PEER_PORT "peer_port" #define SECTION_PEER_PRIVATE "peer_private" #define SECTION_PEERS_MAX "peers_max" -#define SECTION_PEER_SSL_CIPHER_LIST "peer_ssl_cipher_list" #define SECTION_RPC_ALLOW_REMOTE "rpc_allow_remote" #define SECTION_RPC_ADMIN_ALLOW "rpc_admin_allow" #define SECTION_RPC_ADMIN_USER "rpc_admin_user" diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 19971a57f..40387f2ed 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -254,9 +254,6 @@ Config::Config () RPC_ALLOW_REMOTE = false; RPC_ADMIN_ALLOW.push_back (beast::IP::Endpoint::from_string("127.0.0.1")); - // By default, allow anonymous DH. - PEER_SSL_CIPHER_LIST = "ALL:!LOW:!EXP:!MD5:@STRENGTH"; - PEER_PRIVATE = false; PEERS_MAX = 0; // indicates "use default" @@ -638,8 +635,6 @@ void Config::load () } } - (void) getSingleSection (secConfig, SECTION_PEER_SSL_CIPHER_LIST, PEER_SSL_CIPHER_LIST); - if (getSingleSection (secConfig, SECTION_NETWORK_QUORUM, strTemp)) NETWORK_QUORUM = beast::lexicalCastThrow (strTemp); diff --git a/src/ripple/overlay/Overlay.h b/src/ripple/overlay/Overlay.h index f5f0c0b4c..f399b66e9 100644 --- a/src/ripple/overlay/Overlay.h +++ b/src/ripple/overlay/Overlay.h @@ -21,15 +21,13 @@ #define RIPPLE_OVERLAY_OVERLAY_H_INCLUDED #include - -// VFALCO TODO Remove this include dependency it shouldn't be needed -#include - #include #include - +#include #include // +namespace boost { namespace asio { namespace ssl { class context; } } } + namespace ripple { /** Manages the set of connected peers. */ @@ -46,14 +44,27 @@ protected: : Stoppable ("Overlay", parent) , beast::PropertyStream::Source ("peers") { - } public: + enum class Promote + { + automatic, + never, + always + }; + + struct Setup + { + bool auto_connect = true; + bool http_handshake = false; + Promote promote = Promote::automatic; + std::shared_ptr context; + }; + typedef std::vector PeerSequence; - virtual - ~Overlay () = default; + virtual ~Overlay() = default; /** Establish a peer connection to the specified endpoint. The call returns immediately, the connection attempt is diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp index 54773b7d9..7f690bc0e 100644 --- a/src/ripple/overlay/impl/OverlayImpl.cpp +++ b/src/ripple/overlay/impl/OverlayImpl.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -51,14 +52,16 @@ struct get_peer_json //------------------------------------------------------------------------------ -OverlayImpl::OverlayImpl (Stoppable& parent, +OverlayImpl::OverlayImpl ( + Setup const& setup, + Stoppable& parent, Resource::Manager& resourceManager, SiteFiles::Manager& siteFiles, beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service, - boost::asio::ssl::context& ssl_context) + boost::asio::io_service& io_service) : Overlay (parent) + , setup_(setup) , m_child_count (1) , m_journal (deprecatedLogs().journal("Overlay")) , m_resourceManager (resourceManager) @@ -66,7 +69,6 @@ OverlayImpl::OverlayImpl (Stoppable& parent, pathToDbFileOrDirectory, get_seconds_clock (), deprecatedLogs().journal("PeerFinder")))) , m_io_service (io_service) - , m_ssl_context (ssl_context) , timer_(io_service) , m_resolver (resolver) , m_nextShortId (0) @@ -109,7 +111,7 @@ OverlayImpl::accept (socket_type&& socket) PeerImp::ptr const peer (std::make_shared ( std::move (socket), remote_endpoint, *this, m_resourceManager, - *m_peerFinder, slot, m_ssl_context)); + *m_peerFinder, slot, setup_.context)); { std::lock_guard lock (m_mutex); @@ -146,7 +148,7 @@ OverlayImpl::connect (beast::IP::Endpoint const& remote_endpoint) PeerImp::ptr const peer (std::make_shared ( remote_endpoint, m_io_service, *this, m_resourceManager, - *m_peerFinder, slot, m_ssl_context)); + *m_peerFinder, slot, setup_.context)); { std::lock_guard lock (m_mutex); @@ -436,10 +438,10 @@ OverlayImpl::getActivePeers () ret.reserve (m_publicKeyMap.size ()); - for (auto const& pair : m_publicKeyMap) + for (auto const& e : m_publicKeyMap) { - assert (pair.second); - ret.push_back (pair.second); + assert (e.second); + ret.push_back (e.second); } return ret; @@ -508,18 +510,37 @@ OverlayImpl::do_timer (yield_context yield) //------------------------------------------------------------------------------ +Overlay::Setup +setup_Overlay (BasicConfig const& config) +{ + Overlay::Setup setup; + auto const& section = config.section("overlay"); + set (setup.http_handshake, "http_handshake", section); + set (setup.auto_connect, "auto_connect", section); + std::string promote; + set (promote, "become_superpeer", section); + if (promote == "never") + setup.promote = Overlay::Promote::never; + else if (promote == "always") + setup.promote = Overlay::Promote::always; + else + setup.promote = Overlay::Promote::automatic; + setup.context = make_ssl_context(); + return setup; +} + std::unique_ptr make_Overlay ( + Overlay::Setup const& setup, beast::Stoppable& parent, Resource::Manager& resourceManager, SiteFiles::Manager& siteFiles, beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service, - boost::asio::ssl::context& ssl_context) + boost::asio::io_service& io_service) { - return std::make_unique (parent, resourceManager, siteFiles, - pathToDbFileOrDirectory, resolver, io_service, ssl_context); + return std::make_unique (setup, parent, resourceManager, + siteFiles, pathToDbFileOrDirectory, resolver, io_service); } } diff --git a/src/ripple/overlay/impl/OverlayImpl.h b/src/ripple/overlay/impl/OverlayImpl.h index 8b7b64899..4e5968606 100644 --- a/src/ripple/overlay/impl/OverlayImpl.h +++ b/src/ripple/overlay/impl/OverlayImpl.h @@ -59,6 +59,8 @@ private: typedef hash_map PeerByShortId; + Setup setup_; + // VFALCO TODO Change to regular mutex and eliminate re-entrancy std::recursive_mutex m_mutex; @@ -74,7 +76,6 @@ private: std::unique_ptr m_peerFinder; boost::asio::io_service& m_io_service; - boost::asio::ssl::context& m_ssl_context; boost::asio::basic_waitable_timer timer_; /** Associates slots to peers. */ @@ -101,16 +102,19 @@ private: //-------------------------------------------------------------------------- public: - OverlayImpl (Stoppable& parent, - Resource::Manager& resourceManager, - SiteFiles::Manager& siteFiles, - beast::File const& pathToDbFileOrDirectory, - Resolver& resolver, - boost::asio::io_service& io_service, - boost::asio::ssl::context& ssl_context); + OverlayImpl (Setup const& setup, Stoppable& parent, + Resource::Manager& resourceManager, SiteFiles::Manager& siteFiles, + beast::File const& pathToDbFileOrDirectory, Resolver& resolver, + boost::asio::io_service& io_service); ~OverlayImpl (); + Setup const& + setup() const + { + return setup_; + } + PeerSequence getActivePeers () override; diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index 3af6d4049..d98714638 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -22,16 +22,19 @@ #include #include #include +#include // namespace ripple { PeerImp::PeerImp (socket_type&& socket, beast::IP::Endpoint remoteAddress, OverlayImpl& overlay, Resource::Manager& resourceManager, PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot, - boost::asio::ssl::context& ssl_context) + std::shared_ptr const& context) : journal_ (deprecatedLogs().journal("Peer")) - , socket_ (std::move (socket)) - , stream_ (socket_, ssl_context) + , ssl_bundle_(std::make_unique( + context, std::move(socket))) + , socket_ (ssl_bundle_->socket) + , stream_ (ssl_bundle_->stream) , strand_ (socket_.get_io_service()) , timer_ (socket_.get_io_service()) , remote_address_ (remoteAddress) @@ -49,10 +52,12 @@ PeerImp::PeerImp (beast::IP::Endpoint remoteAddress, boost::asio::io_service& io_service, OverlayImpl& overlay, Resource::Manager& resourceManager, PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot, - boost::asio::ssl::context& ssl_context) + std::shared_ptr const& context) : journal_ (deprecatedLogs().journal("Peer")) - , socket_ (io_service) - , stream_ (socket_, ssl_context) + , ssl_bundle_(std::make_unique( + context, io_service)) + , socket_ (ssl_bundle_->socket) + , stream_ (ssl_bundle_->stream) , strand_ (socket_.get_io_service()) , timer_ (socket_.get_io_service()) , remote_address_ (remoteAddress) @@ -381,15 +386,16 @@ PeerImp::on_connect_ssl (error_code ec) return; } -#if RIPPLE_STRUCTURED_OVERLAY_CLIENT - beast::http::message req (make_request()); - beast::http::write (write_buffer_, req); - on_write_http_request (error_code(), 0); - -#else - do_protocol_start(); - -#endif + if (overlay_.setup().http_handshake) + { + beast::http::message req (make_request()); + beast::http::write (write_buffer_, req); + on_write_http_request (error_code(), 0); + } + else + { + do_protocol_start(); + } } // Called repeatedly with the http request data @@ -525,12 +531,10 @@ PeerImp::on_accept_ssl (error_code ec) return; } -#if RIPPLE_STRUCTURED_OVERLAY_SERVER +#if 1 on_read_http_detect (error_code(), 0); - #else do_protocol_start(); - #endif } diff --git a/src/ripple/overlay/impl/PeerImp.h b/src/ripple/overlay/impl/PeerImp.h index 918aa0cad..23526bd5c 100644 --- a/src/ripple/overlay/impl/PeerImp.h +++ b/src/ripple/overlay/impl/PeerImp.h @@ -32,19 +32,13 @@ #include #include #include - -// VFALCO This is unfortunate. Comment this out and -// just include what is needed. -#include - +#include // VFALCO REMOVE #include #include #include +#include #include #include - -#include - #include namespace ripple { @@ -110,8 +104,9 @@ private: static const size_t sslMinimumFinishedLength = 12; beast::Journal journal_; - socket_type socket_; - stream_type stream_; + std::unique_ptr ssl_bundle_; + socket_type& socket_; + stream_type& stream_; boost::asio::io_service::strand strand_; boost::asio::deadline_timer timer_; @@ -187,7 +182,7 @@ public: PeerImp (socket_type&& socket, beast::IP::Endpoint remoteAddress, OverlayImpl& overlay, Resource::Manager& resourceManager, PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot, - boost::asio::ssl::context& ssl_context); + std::shared_ptr const& context); /** Create an outgoing peer @note Construction of outbound peers is a two step process: a second @@ -198,7 +193,7 @@ public: PeerImp (beast::IP::Endpoint remoteAddress, boost::asio::io_service& io_service, OverlayImpl& overlay, Resource::Manager& resourceManager, PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot, - boost::asio::ssl::context& ssl_context); + std::shared_ptr const& context); virtual ~PeerImp (); diff --git a/src/ripple/overlay/make_Overlay.h b/src/ripple/overlay/make_Overlay.h index e8a5644ce..d5e921382 100644 --- a/src/ripple/overlay/make_Overlay.h +++ b/src/ripple/overlay/make_Overlay.h @@ -21,14 +21,11 @@ #define RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED #include - #include #include #include - #include #include - #include #include @@ -37,25 +34,19 @@ namespace ripple { // VFALCO This is separated so that users of the Overlay interface do not need // to know about creation details such as asio or ssl. -/** Creates the implementation of Overlay. +Overlay::Setup +setup_Overlay (BasicConfig const& config); - @param parent - @param resourceManager - @param siteFiles - @param pathToDbFileOrDirectory - @param resolver - @param io_service - @param context -*/ +/** Creates the implementation of Overlay. */ std::unique_ptr make_Overlay ( + Overlay::Setup const& setup, beast::Stoppable& parent, Resource::Manager& resourceManager, SiteFiles::Manager& siteFiles, beast::File const& pathToDbFileOrDirectory, Resolver& resolver, - boost::asio::io_service& io_service, - boost::asio::ssl::context& ssl_context); + boost::asio::io_service& io_service); } // ripple diff --git a/src/ripple/types/ByteOrder.h b/src/ripple/types/ByteOrder.h index 9fe229be7..b7819df6f 100644 --- a/src/ripple/types/ByteOrder.h +++ b/src/ripple/types/ByteOrder.h @@ -26,7 +26,7 @@ namespace ripple { // Reference: http://www.mail-archive.com/licq-commits@googlegroups.com/msg02334.html -#if BEAST_WIN32 +#ifdef _MSC_VER extern uint64_t htobe64 (uint64_t value); extern uint64_t be64toh (uint64_t value); extern uint32_t htobe32 (uint32_t value);