diff --git a/doc/rippled-example.cfg b/doc/rippled-example.cfg index 14f87e3ca6..33ae49ed82 100644 --- a/doc/rippled-example.cfg +++ b/doc/rippled-example.cfg @@ -84,6 +84,16 @@ # # # +# [ips_fixed] +# +# List of IP addresses to which rippled should always maintain peer +# connections with. This is useful for manually forming private networks, +# for example to configure a validation server that connects to the +# Ripple network through a public-facing server, or for building a set +# of cluster peers. +# +# +# # [peer_ip] # # IP address or domain to bind to allow external connections from peers. diff --git a/src/ripple/peerfinder/api/Manager.h b/src/ripple/peerfinder/api/Manager.h index c42d7e8299..9b86e0c8d6 100644 --- a/src/ripple/peerfinder/api/Manager.h +++ b/src/ripple/peerfinder/api/Manager.h @@ -50,16 +50,24 @@ public: */ virtual void setConfig (Config const& config) = 0; + /** Add a set of strings for peers that should always be connected. + This is useful for maintaining a private cluster of peers. + If a string is not parseable as a numeric IP address it will + be passed to a DNS resolver to perform a lookup. + */ + virtual void addFixedPeers ( + std::vector const& strings) = 0; + /** Add a set of strings as fallback IPEndpoint sources. @param name A label used for diagnostics. */ - virtual void addStrings (std::string const& name, + virtual void addFallbackStrings (std::string const& name, std::vector const& strings) = 0; /** Add a URL as a fallback location to obtain IPEndpoint sources. @param name A label used for diagnostics. */ - virtual void addURL (std::string const& name, + virtual void addFallbackURL (std::string const& name, std::string const& url) = 0; /** Called when a new peer connection is established. diff --git a/src/ripple/peerfinder/impl/Logic.h b/src/ripple/peerfinder/impl/Logic.h index 079c0151a2..7d2d7d85f0 100644 --- a/src/ripple/peerfinder/impl/Logic.h +++ b/src/ripple/peerfinder/impl/Logic.h @@ -40,7 +40,10 @@ typedef boost::multi_index_container < PeerInfo, boost::multi_index::indexed_by < boost::multi_index::hashed_unique < BOOST_MULTI_INDEX_MEMBER(PeerFinder::PeerInfo,PeerID,id), - PeerID::hasher> + PeerID::hasher>, + boost::multi_index::hashed_non_unique < + BOOST_MULTI_INDEX_MEMBER(PeerFinder::PeerInfo,IPEndpoint,address), + IPEndpoint::hasher> > > Peers; @@ -80,6 +83,13 @@ public: Journal m_journal; Config m_config; + // The number of fixed peers that are currently connected + int m_fixedPeersConnected; + + // A list of peers that should always be connected + typedef std::set FixedPeers; + FixedPeers m_fixedPeers; + // A list of dynamic sources to consult as a fallback std::vector > m_sources; @@ -104,6 +114,7 @@ public: , m_store (store) , m_checker (checker) , m_journal (journal) + , m_fixedPeersConnected (0) , m_cache (journal) , m_legacyCache (store, journal) { @@ -165,18 +176,34 @@ public: // void makeOutgoingConnections () { + std::vector list; + if (m_slots.outDesired > m_slots.outboundCount) { int const needed (std::min ( m_slots.outDesired - m_slots.outboundCount, int (maxAddressesPerAttempt))); - std::vector list; m_legacyCache.get (needed, list); + } + + if (m_fixedPeersConnected < m_fixedPeers.size()) + { + list.reserve (list.size() + m_fixedPeers.size() - m_fixedPeersConnected); + + for (FixedPeers::const_iterator iter (m_fixedPeers.begin()); + iter != m_fixedPeers.end(); ++iter) + { + if (m_peers.get<1>().find (*iter) != m_peers.get<1>().end()) + { + list.push_back (*iter); + } + } + } #if RIPPLE_USE_PEERFINDER + if (! list.empty()) m_callback.connectPeerEndpoints (list); #endif - } } //-------------------------------------------------------------------------- @@ -191,6 +218,23 @@ public: m_slots.update (m_config); } + void addFixedPeers (std::vector const& strings) + { + for (std::vector ::const_iterator iter (strings.begin()); + iter != strings.end(); ++iter) + { + IPEndpoint ep (IPEndpoint::from_string (*iter)); + if (! ep.empty ()) + { + m_fixedPeers.insert (ep); + } + else + { + // VFALCO TODO Attempt name resolution + } + } + } + void addStaticSource (SharedPtr const& source) { fetch (source); diff --git a/src/ripple/peerfinder/impl/Manager.cpp b/src/ripple/peerfinder/impl/Manager.cpp index e254918d03..e82fa50e73 100644 --- a/src/ripple/peerfinder/impl/Manager.cpp +++ b/src/ripple/peerfinder/impl/Manager.cpp @@ -240,7 +240,19 @@ public: config))); } - void addStrings (std::string const& name, + void addFixedPeers ( + std::vector const& strings) + { +#if 1 + m_logic.addFixedPeers (strings); +#else + m_queue.dispatch (m_context.wrap ( + bind (&Logic::addFixedPeers, &m_logic, + std::vector (strings)))); +#endif + } + + void addFallbackStrings (std::string const& name, std::vector const& strings) { m_queue.dispatch ( @@ -250,8 +262,9 @@ public: SourceStrings::New (name, strings)))); } - void addURL (std::string const& name, std::string const& url) + void addFallbackURL (std::string const& name, std::string const& url) { + // VFALCO TODO This needs to be implemented } void onPeerConnected (PeerID const& id, diff --git a/src/ripple_app/peers/Peers.cpp b/src/ripple_app/peers/Peers.cpp index 9fefb09939..0ebc8a48cc 100644 --- a/src/ripple_app/peers/Peers.cpp +++ b/src/ripple_app/peers/Peers.cpp @@ -132,7 +132,11 @@ public: m_peerFinder->setConfig (config); // Add the static IPs from the rippled.cfg file - m_peerFinder->addStrings ("rippled.cfg", getConfig().IPS); + m_peerFinder->addFallbackStrings ("rippled.cfg", getConfig().IPS); + + // Add the ips_fixed from the rippled.cfg file + if (! getConfig().RUN_STANDALONE) + m_peerFinder->addFixedPeers (getConfig().IPS_FIXED); } void sendPeerEndpoints (PeerFinder::PeerID const& id, @@ -297,7 +301,7 @@ public: void policyEnforce (); // configured connections - void makeConfigured (); + void legacyConnectFixedIPs (); }; void splitIpPort (const std::string& strIpPort, std::string& strIp, int& iPort) @@ -525,7 +529,7 @@ void PeersImp::policyEnforce () if (((++mPhase) % 12) == 0) { WriteLog (lsTRACE, Peers) << "Making configured connections"; - makeConfigured (); + legacyConnectFixedIPs (); } // Schedule next enforcement. @@ -974,12 +978,16 @@ void PeersImp::scanHandler (const boost::system::error_code& ecResult) } } -void PeersImp::makeConfigured () +// Legacy policy enforcement: Maintain peer connections +// to the configured set of fixed IP addresses. Note that this +// is replaced by the new PeerFinder. +// +void PeersImp::legacyConnectFixedIPs () { if (getConfig ().RUN_STANDALONE) return; - BOOST_FOREACH (const std::string & strPeer, getConfig ().IPS) + BOOST_FOREACH (const std::string & strPeer, getConfig ().IPS_FIXED) { std::string strIP; int iPort; diff --git a/src/ripple_app/peers/Peers.h b/src/ripple_app/peers/Peers.h index b4db7187b3..76d5f0012c 100644 --- a/src/ripple_app/peers/Peers.h +++ b/src/ripple_app/peers/Peers.h @@ -97,7 +97,7 @@ public: virtual void policyEnforce () = 0; // VFALCO This and others can be made private // configured connections - virtual void makeConfigured () = 0; + virtual void legacyConnectFixedIPs () = 0; }; // VFALCO TODO Put this in some group of utilities diff --git a/src/ripple_app/peers/UniqueNodeList.cpp b/src/ripple_app/peers/UniqueNodeList.cpp index 1516f17fc7..f988de2e71 100644 --- a/src/ripple_app/peers/UniqueNodeList.cpp +++ b/src/ripple_app/peers/UniqueNodeList.cpp @@ -503,13 +503,18 @@ public: nodeNetwork (); } - if (!getConfig ().IPS.empty ()) + // Take the set of entries in IPS_FIXED and insert them into the + // "legacy endpoint" database so they will be served as IP addresses + // in the legacy mtPEERS message. Note that this is all replaced by + // the new PeerFinder. + // + if (!getConfig ().IPS_FIXED.empty ()) { std::vector vstrValues; - vstrValues.reserve (getConfig ().IPS.size ()); + vstrValues.reserve (getConfig ().IPS_FIXED.size ()); - BOOST_FOREACH (const std::string & strPeer, getConfig ().IPS) + BOOST_FOREACH (const std::string & strPeer, getConfig ().IPS_FIXED) { std::string strIP; int iPort; diff --git a/src/ripple_core/functional/Config.cpp b/src/ripple_core/functional/Config.cpp index 6699441620..58fe5fdb63 100644 --- a/src/ripple_core/functional/Config.cpp +++ b/src/ripple_core/functional/Config.cpp @@ -253,7 +253,6 @@ void Config::load () if (smtTmp) { validators = *smtTmp; - // SectionEntriesPrint(&validators, SECTION_VALIDATORS); } smtTmp = SectionEntries (secConfig, SECTION_CLUSTER_NODES); @@ -261,7 +260,6 @@ void Config::load () if (smtTmp) { CLUSTER_NODES = *smtTmp; - // SectionEntriesPrint(&CLUSTER_NODES, SECTION_CLUSTER_NODES); } smtTmp = SectionEntries (secConfig, SECTION_IPS); @@ -269,7 +267,13 @@ void Config::load () if (smtTmp) { IPS = *smtTmp; - // SectionEntriesPrint(&IPS, SECTION_IPS); + } + + smtTmp = SectionEntries (secConfig, SECTION_IPS_FIXED); + + if (smtTmp) + { + IPS_FIXED = *smtTmp; } smtTmp = SectionEntries (secConfig, SECTION_SNTP); diff --git a/src/ripple_core/functional/Config.h b/src/ripple_core/functional/Config.h index 557ad4f510..8a27b0ea22 100644 --- a/src/ripple_core/functional/Config.h +++ b/src/ripple_core/functional/Config.h @@ -344,6 +344,7 @@ public: std::string VALIDATORS_URI; // URI of validators.txt. std::string VALIDATORS_BASE; // Name with testnet-, if needed. std::vector IPS; // Peer IPs from rippled.cfg. + std::vector IPS_FIXED; // Fixed Peer IPs from rippled.cfg. std::vector SNTP_SERVERS; // SNTP servers from rippled.cfg. enum StartUpType diff --git a/src/ripple_core/functional/ConfigSections.h b/src/ripple_core/functional/ConfigSections.h index 542ba65fb7..7a8086a8b3 100644 --- a/src/ripple_core/functional/ConfigSections.h +++ b/src/ripple_core/functional/ConfigSections.h @@ -48,6 +48,7 @@ struct ConfigSection #define SECTION_FEE_OWNER_RESERVE "fee_owner_reserve" #define SECTION_LEDGER_HISTORY "ledger_history" #define SECTION_IPS "ips" +#define SECTION_IPS_FIXED "ips_fixed" #define SECTION_NETWORK_QUORUM "network_quorum" #define SECTION_NODE_SEED "node_seed" #define SECTION_NODE_SIZE "node_size"