Config improvements:

* More fine-grained Section mutators
* Add remap for mapping legacy single sections to key value pairs
* Add output stream operators for BasicConfig and Section
* Allow section values to be overwritten from command line
* Update rpc key/value configs from command line
* Add RPC::Setup with defaults and remap legacy rpc sections
This commit is contained in:
Vinnie Falco
2014-09-27 18:22:56 -07:00
parent 2936bbfae8
commit d618581060
8 changed files with 223 additions and 42 deletions

View File

@@ -309,7 +309,8 @@ public:
, m_deprecatedUNL (make_UniqueNodeList (*m_jobQueue)) , m_deprecatedUNL (make_UniqueNodeList (*m_jobQueue))
, m_rpcHTTPServer (make_RPCHTTPServer (*m_networkOPs, , m_rpcHTTPServer (make_RPCHTTPServer (*m_networkOPs,
*m_jobQueue, *m_networkOPs, *m_resourceManager)) *m_jobQueue, *m_networkOPs, *m_resourceManager,
setup_RPC(getConfig()["rpc"])))
// passive object, not a Service // passive object, not a Service
, m_rpcServerHandler (*m_networkOPs, *m_resourceManager) , m_rpcServerHandler (*m_networkOPs, *m_resourceManager)

View File

@@ -344,6 +344,7 @@ int run (int argc, char** argv)
if (vm.count ("rpc_ip")) if (vm.count ("rpc_ip"))
{ {
getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as <std::string> ()); getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as <std::string> ());
getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as<std::string>());
} }
// Override the RPC destination port number // Override the RPC destination port number
@@ -352,6 +353,7 @@ int run (int argc, char** argv)
{ {
// VFALCO TODO This should be a short. // VFALCO TODO This should be a short.
getConfig ().setRpcPort (vm ["rpc_port"].as <int> ()); getConfig ().setRpcPort (vm ["rpc_port"].as <int> ());
getConfig().overwrite("rpc", "port", vm["rpc_port"].as<std::string>());
} }
if (vm.count ("quorum")) if (vm.count ("quorum"))

View File

@@ -38,9 +38,11 @@ public:
RPCServerHandler m_deprecatedHandler; RPCServerHandler m_deprecatedHandler;
HTTP::Server m_server; HTTP::Server m_server;
std::unique_ptr <RippleSSLContext> m_context; std::unique_ptr <RippleSSLContext> m_context;
RPC::Setup setup_;
RPCHTTPServerImp (Stoppable& parent, JobQueue& jobQueue, RPCHTTPServerImp (Stoppable& parent, JobQueue& jobQueue,
NetworkOPs& networkOPs, Resource::Manager& resourceManager) NetworkOPs& networkOPs, Resource::Manager& resourceManager,
RPC::Setup const& setup)
: RPCHTTPServer (parent) : RPCHTTPServer (parent)
, m_resourceManager (resourceManager) , m_resourceManager (resourceManager)
, m_journal (deprecatedLogs().journal("HTTP-RPC")) , m_journal (deprecatedLogs().journal("HTTP-RPC"))
@@ -48,18 +50,13 @@ public:
, m_networkOPs (networkOPs) , m_networkOPs (networkOPs)
, m_deprecatedHandler (networkOPs, resourceManager) , m_deprecatedHandler (networkOPs, resourceManager)
, m_server (*this, deprecatedLogs().journal("HTTP")) , m_server (*this, deprecatedLogs().journal("HTTP"))
, setup_ (setup)
{ {
if (getConfig ().RPC_SECURE == 0) if (setup_.secure)
{
m_context.reset (RippleSSLContext::createBare ());
}
else
{
m_context.reset (RippleSSLContext::createAuthenticated ( m_context.reset (RippleSSLContext::createAuthenticated (
getConfig ().RPC_SSL_KEY, setup_.ssl_key, setup_.ssl_cert, setup_.ssl_chain));
getConfig ().RPC_SSL_CERT, else
getConfig ().RPC_SSL_CHAIN)); m_context.reset (RippleSSLContext::createBare());
}
} }
~RPCHTTPServerImp() ~RPCHTTPServerImp()
@@ -70,10 +67,9 @@ public:
void void
setup (beast::Journal journal) override setup (beast::Journal journal) override
{ {
if (! getConfig ().getRpcIP().empty () && if (! setup_.ip.empty() && setup_.port != 0)
getConfig ().getRpcPort() != 0)
{ {
auto ep = beast::IP::Endpoint::from_string (getConfig().getRpcIP()); auto ep = beast::IP::Endpoint::from_string (setup_.ip);
// VFALCO TODO IP address should not have an "unspecified" state // VFALCO TODO IP address should not have an "unspecified" state
//if (! is_unspecified (ep)) //if (! is_unspecified (ep))
@@ -81,8 +77,8 @@ public:
HTTP::Port port; HTTP::Port port;
port.security = HTTP::Port::Security::allow_ssl; port.security = HTTP::Port::Security::allow_ssl;
port.addr = ep.at_port(0); port.addr = ep.at_port(0);
if (getConfig ().getRpcPort() != 0) if (setup_.port != 0)
port.port = getConfig ().getRpcPort(); port.port = setup_.port;
else else
port.port = ep.port(); port.port = ep.port();
port.context = m_context.get (); port.context = m_context.get ();
@@ -123,7 +119,7 @@ public:
onAccept (HTTP::Session& session) override onAccept (HTTP::Session& session) override
{ {
// Reject non-loopback connections if RPC_ALLOW_REMOTE is not set // Reject non-loopback connections if RPC_ALLOW_REMOTE is not set
if (! getConfig().RPC_ALLOW_REMOTE && if (! setup_.allow_remote &&
! beast::IP::is_loopback (session.remoteAddress())) ! beast::IP::is_loopback (session.remoteAddress()))
{ {
session.close (false); session.close (false);
@@ -295,10 +291,11 @@ RPCHTTPServer::RPCHTTPServer (Stoppable& parent)
std::unique_ptr <RPCHTTPServer> std::unique_ptr <RPCHTTPServer>
make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue, make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue,
NetworkOPs& networkOPs, Resource::Manager& resourceManager) NetworkOPs& networkOPs, Resource::Manager& resourceManager,
RPC::Setup const& setup)
{ {
return std::make_unique <RPCHTTPServerImp> ( return std::make_unique <RPCHTTPServerImp> (
parent, jobQueue, networkOPs, resourceManager); parent, jobQueue, networkOPs, resourceManager, setup);
} }
} }

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED #ifndef RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED
#define RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED #define RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED
#include <ripple/core/Config.h>
#include <beast/utility/Journal.h> #include <beast/utility/Journal.h>
#include <beast/utility/PropertyStream.h> #include <beast/utility/PropertyStream.h>
#include <beast/cxx14/memory.h> // <memory> #include <beast/cxx14/memory.h> // <memory>
@@ -48,7 +49,8 @@ public:
std::unique_ptr <RPCHTTPServer> std::unique_ptr <RPCHTTPServer>
make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue, make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue,
NetworkOPs& networkOPs, Resource::Manager& resourceManager); NetworkOPs& networkOPs, Resource::Manager& resourceManager,
RPC::Setup const& setup);
} // ripple } // ripple

View File

@@ -93,9 +93,30 @@ public:
} }
/** @} */ /** @} */
/** Overwrite a key/value pair with a command line argument
If the section does not exist it is created.
The previous value, if any, is overwritten.
*/
void
overwrite (std::string const& section, std::string const& key,
std::string const& value);
friend
std::ostream&
operator<< (std::ostream& ss, BasicConfig const& c);
protected: protected:
void void
build (IniFileSections const& ifs); build (IniFileSections const& ifs);
/** Insert a legacy single section as a key/value pair.
Does nothing if the section does not exist, or does not contain
a single line that is not a key/value pair.
@deprecated
*/
void
remap (std::string const& legacy_section,
std::string const& key, std::string const& new_section);
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -456,10 +477,37 @@ public:
int getSize (SizedItemName); int getSize (SizedItemName);
void setup (std::string const& strConf, bool bQuiet); void setup (std::string const& strConf, bool bQuiet);
void load (); void load ();
private:
void build_legacy();
}; };
extern Config& getConfig (); extern Config& getConfig ();
//------------------------------------------------------------------------------
namespace RPC {
struct Setup
{
bool allow_remote = false;
std::string admin_user;
std::string admin_password;
std::string ip;
int port = 5001;
std::string user;
std::string password;
bool secure = false;
std::string ssl_cert;
std::string ssl_chain;
std::string ssl_key;
};
}
RPC::Setup
setup_RPC (Section const& s);
} // ripple } // ripple
#endif #endif

View File

@@ -23,6 +23,7 @@
#include <beast/utility/ci_char_traits.h> #include <beast/utility/ci_char_traits.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <map> #include <map>
#include <ostream>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -42,6 +43,32 @@ public:
/** Create an empty section. */ /** Create an empty section. */
Section() = default; Section() = default;
/** Returns the number of key/value pairs. */
std::size_t
keys() const
{
return map_.size();
}
/** Returns all the lines in the section. */
std::vector <std::string> const&
lines() const
{
return lines_;
}
/** Set a key/value pair.
The previous value is discarded.
*/
void
set (std::string const& key, std::string const& value);
/** Append a line to this section.
If the line can be parsed as a key/value pair it is added to the map.
*/
void
append (std::string const& line);
/** Append a set of lines to this section. /** Append a set of lines to this section.
Parsable key/value pairs are also added to the map. Parsable key/value pairs are also added to the map.
*/ */
@@ -57,6 +84,10 @@ public:
*/ */
std::pair <std::string, bool> std::pair <std::string, bool>
find (std::string const& name) const; find (std::string const& name) const;
friend
std::ostream&
operator<< (std::ostream&, Section const& section);
}; };
/** Set a value from a configuration Section /** Set a value from a configuration Section

View File

@@ -24,6 +24,7 @@
#include <ripple/net/HTTPClient.h> #include <ripple/net/HTTPClient.h>
#include <beast/http/ParsedURL.h> #include <beast/http/ParsedURL.h>
#include <beast/module/core/text/LexicalCast.h> #include <beast/module/core/text/LexicalCast.h>
#include <beast/streams/debug_ostream.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
@@ -31,6 +32,10 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#ifndef DUMP_CONFIG
#define DUMP_CONFIG 0
#endif
namespace ripple { namespace ripple {
// //
@@ -237,17 +242,48 @@ BasicConfig::section (std::string const& name) const
return iter->second; return iter->second;
} }
void
BasicConfig::remap (std::string const& legacy_section,
std::string const& key, std::string const& new_section)
{
auto const iter = map_.find (legacy_section);
if (iter == map_.end())
return;
if (iter->second.keys() != 0)
return;
if (iter->second.lines().size() != 1)
return;
auto& s = map_[new_section];
s.append (iter->second.lines().front());
s.set (key, iter->second.lines().front());
}
void
BasicConfig::overwrite (std::string const& section, std::string const& key,
std::string const& value)
{
auto const result = map_.emplace (section, Section{});
result.first->second.set (key, value);
}
void void
BasicConfig::build (IniFileSections const& ifs) BasicConfig::build (IniFileSections const& ifs)
{ {
for (auto const& entry : ifs) for (auto const& entry : ifs)
{ {
auto const result = map_.insert (std::make_pair ( auto const result = map_.emplace (entry.first, Section{});
entry.first, Section{}));
result.first->second.append (entry.second); result.first->second.append (entry.second);
} }
} }
std::ostream&
operator<< (std::ostream& ss, BasicConfig const& c)
{
for (auto const& s : c.map_)
ss << "[" << s.first << "]\n" << s.second;
return ss;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// //
// Config (DEPRECATED) // Config (DEPRECATED)
@@ -458,6 +494,7 @@ void Config::load ()
std::string strTemp; std::string strTemp;
build (secConfig); build (secConfig);
build_legacy();
// XXX Leak // XXX Leak
IniFileSections::mapped_type* smtTmp; IniFileSections::mapped_type* smtTmp;
@@ -973,4 +1010,55 @@ beast::File const& Config::getModuleDatabasePath ()
return m_moduleDbPath; return m_moduleDbPath;
} }
//------------------------------------------------------------------------------
void
Config::build_legacy ()
{
//--------------------------------------------------------------------------
//
// [rpc]
//
//--------------------------------------------------------------------------
remap("rpc_allow_remote", "allow_remote", "rpc");
//remap("rpc_admin_allow", "admin_allow", "rpc"); // Not a key-value pair
remap("rpc_admin_user", "admin_user", "rpc");
remap("rpc_admin_password", "admin_password", "rpc");
remap("rpc_ip", "ip", "rpc");
remap("rpc_port", "port", "rpc");
remap("rpc_user", "user", "rpc");
remap("rpc_password", "password", "rpc");
//remap("rpc_startup", "startup", "rpc"); // Not a key-value pair
remap("rpc_secure", "secure", "rpc");
remap("rpc_ssl_cert", "ssl_cert", "rpc");
remap("rpc_ssl_chain", "ssl_chain", "rpc");
remap("rpc_ssl_key", "ssl_key", "rpc");
#if DUMP_CONFIG
beast::debug_ostream log;
log << (BasicConfig const&)*this;
#endif
}
//------------------------------------------------------------------------------
RPC::Setup
setup_RPC (Section const& s)
{
RPC::Setup c;
set (c.allow_remote, "allow_remote", s);
set (c.admin_user, "admin_user", s);
set (c.admin_password, "admin_password", s);
set (c.ip, "ip", s);
set (c.port, "port", s);
set (c.user, "user", s);
set (c.password, "password", s);
set (c.secure, "secure", s);
set (c.ssl_cert, "ssl_cert", s);
set (c.ssl_chain, "ssl_chain", s);
set (c.ssl_key, "ssl_key", s);
return c;
}
} // ripple } // ripple

View File

@@ -19,11 +19,20 @@
#include <ripple/core/Section.h> #include <ripple/core/Section.h>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <algorithm>
namespace ripple { namespace ripple {
void void
Section::append (std::vector <std::string> const& lines) Section::set (std::string const& key, std::string const& value)
{
auto const result = map_.emplace (key, value);
if (! result.second)
result.first->second = value;
}
void
Section::append (std::string const& line)
{ {
// <key> '=' <value> // <key> '=' <value>
static boost::regex const re1 ( static boost::regex const re1 (
@@ -38,25 +47,18 @@ Section::append (std::vector <std::string> const& lines)
, boost::regex_constants::optimize , boost::regex_constants::optimize
); );
boost::smatch match;
lines_.push_back (line);
if (boost::regex_match (line, match, re1))
set (match[1], match[2]);
}
void
Section::append (std::vector <std::string> const& lines)
{
lines_.reserve (lines_.size() + lines.size()); lines_.reserve (lines_.size() + lines.size());
for (auto const& line : lines) std::for_each (lines.begin(), lines.end(),
{ [&](std::string const& line) { this->append (line); });
boost::smatch match;
lines_.push_back (line);
if (boost::regex_match (line, match, re1))
{
/*auto const result =*/ map_.emplace (
std::make_pair (match[1], match[2]));
#if 0
if (! result.second)
{
// If we decide on how to merge values we can do it here.
}
beast::debug_ostream log;
//log << "\"" << match[1] << "\" = \"" << match[2] << "\"";
#endif
}
}
} }
bool bool
@@ -74,4 +76,14 @@ Section::find (std::string const& name) const
return {iter->second, true}; return {iter->second, true};
} }
//------------------------------------------------------------------------------
std::ostream&
operator<< (std::ostream& os, Section const& section)
{
for (auto const& kv : section.map_)
os << kv.first << "=" << kv.second << "\n";
return os;
}
} // ripple } // ripple