Refactor Overlay and add [overlay] config section (experimental):

These changes prepare Overlay for the Universal Port and Hub and Spoke
features.

* Add [overlay configuration section:
The [overlay] section uses the new BasicConfig interface that
supports key-value pairs in the section. Some exposition is added to the
example cfg file. The new settings for overlay are related to the Hub and
Spoke feature which is currently in development. Production servers should
not set these configuration options, they are clearly marked experimental
in the example cfg file.

Other changes:
* Use _MSC_VER to detect Visual Studio
* Use ssl_bundle in Overlay::Peer
* Use shared_ptr to SSL context in Overlay:
* Removed undocumented PEER_SSL_CIPHER_LIST configuration setting
* Add Section::name: The Section object now stores its name for better diagnostic messages.
This commit is contained in:
Vinnie Falco
2014-09-23 17:30:50 -07:00
parent a6c2657062
commit 2fd139b307
15 changed files with 205 additions and 120 deletions

View File

@@ -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.
#
# <key> 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:
#
# <identifier> '=' <value>
#
# Depending on the section and key, different value types are possible:
#
# <integer> A signed integer
# <unsigned> An unsigned integer
# <flag> 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

View File

@@ -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

View File

@@ -193,7 +193,6 @@ public:
std::unique_ptr <DatabaseCon> mLedgerDB;
std::unique_ptr <DatabaseCon> mWalletDB;
std::unique_ptr <SSLContext> m_peerSSLContext;
std::unique_ptr <SSLContext> m_wsSSLContext;
std::unique_ptr <Overlay> m_peers;
std::unique_ptr <RPCDoor> 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)

View File

@@ -39,13 +39,21 @@ using IniFileSections = std::map<std::string, std::vector<std::string>>;
class Section
{
private:
std::string name_;
std::vector <std::string> lines_;
std::vector <std::string> values_;
std::map <std::string, std::string, beast::ci_less> 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

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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"

View File

@@ -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 <std::size_t> (strTemp);

View File

@@ -21,15 +21,13 @@
#define RIPPLE_OVERLAY_OVERLAY_H_INCLUDED
#include <ripple/overlay/Peer.h>
// VFALCO TODO Remove this include dependency it shouldn't be needed
#include <ripple/peerfinder/Slot.h>
#include <beast/threads/Stoppable.h>
#include <beast/utility/PropertyStream.h>
#include <memory>
#include <beast/cxx14/type_traits.h> // <type_traits>
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<boost::asio::ssl::context> context;
};
typedef std::vector <Peer::ptr> PeerSequence;
virtual
~Overlay () = default;
virtual ~Overlay() = default;
/** Establish a peer connection to the specified endpoint.
The call returns immediately, the connection attempt is

View File

@@ -17,6 +17,7 @@
*/
//==============================================================================
#include <ripple/common/RippleSSLContext.h>
#include <ripple/overlay/impl/OverlayImpl.h>
#include <ripple/overlay/impl/PeerDoor.h>
#include <ripple/overlay/impl/PeerImp.h>
@@ -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 <PeerImp> (
std::move (socket), remote_endpoint, *this, m_resourceManager,
*m_peerFinder, slot, m_ssl_context));
*m_peerFinder, slot, setup_.context));
{
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
@@ -146,7 +148,7 @@ OverlayImpl::connect (beast::IP::Endpoint const& remote_endpoint)
PeerImp::ptr const peer (std::make_shared <PeerImp> (
remote_endpoint, m_io_service, *this, m_resourceManager,
*m_peerFinder, slot, m_ssl_context));
*m_peerFinder, slot, setup_.context));
{
std::lock_guard <decltype(m_mutex)> 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 <Overlay>
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 <OverlayImpl> (parent, resourceManager, siteFiles,
pathToDbFileOrDirectory, resolver, io_service, ssl_context);
return std::make_unique <OverlayImpl> (setup, parent, resourceManager,
siteFiles, pathToDbFileOrDirectory, resolver, io_service);
}
}

View File

@@ -59,6 +59,8 @@ private:
typedef hash_map <Peer::ShortId, Peer::ptr> 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 <PeerFinder::Manager> m_peerFinder;
boost::asio::io_service& m_io_service;
boost::asio::ssl::context& m_ssl_context;
boost::asio::basic_waitable_timer <clock_type> 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;

View File

@@ -22,16 +22,19 @@
#include <ripple/overlay/impl/Tuning.h>
#include <beast/streams/debug_ostream.h>
#include <functional>
#include <beast/cxx14/memory.h> // <memory>
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<boost::asio::ssl::context> const& context)
: journal_ (deprecatedLogs().journal("Peer"))
, socket_ (std::move (socket))
, stream_ (socket_, ssl_context)
, ssl_bundle_(std::make_unique<beast::asio::ssl_bundle>(
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<boost::asio::ssl::context> const& context)
: journal_ (deprecatedLogs().journal("Peer"))
, socket_ (io_service)
, stream_ (socket_, ssl_context)
, ssl_bundle_(std::make_unique<beast::asio::ssl_bundle>(
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
}

View File

@@ -32,19 +32,13 @@
#include <ripple/core/LoadFeeTrack.h>
#include <ripple/data/protocol/Protocol.h>
#include <ripple/validators/Manager.h>
// VFALCO This is unfortunate. Comment this out and
// just include what is needed.
#include <ripple/unity/app.h>
#include <ripple/unity/app.h> // VFALCO REMOVE
#include <beast/asio/IPAddressConversion.h>
#include <beast/asio/placeholders.h>
#include <beast/asio/streambuf.h>
#include <beast/asio/ssl_bundle.h>
#include <beast/http/message.h>
#include <beast/http/parser.h>
#include <boost/foreach.hpp>
#include <cstdint>
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<beast::asio::ssl_bundle> 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<boost::asio::ssl::context> 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<boost::asio::ssl::context> const& context);
virtual
~PeerImp ();

View File

@@ -21,14 +21,11 @@
#define RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED
#include <ripple/overlay/Overlay.h>
#include <ripple/resource/api/Manager.h>
#include <ripple/sitefiles/Sitefiles.h>
#include <ripple/common/Resolver.h>
#include <beast/threads/Stoppable.h>
#include <beast/module/core/files/File.h>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ssl/context.hpp>
@@ -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 <Overlay>
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

View File

@@ -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);