diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index c89112342..12787fe4a 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -309,7 +309,8 @@ public: , m_deprecatedUNL (make_UniqueNodeList (*m_jobQueue)) , 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 , m_rpcServerHandler (*m_networkOPs, *m_resourceManager) diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp index 25a5105ac..5311ce2b7 100644 --- a/src/ripple/app/main/Main.cpp +++ b/src/ripple/app/main/Main.cpp @@ -344,6 +344,7 @@ int run (int argc, char** argv) if (vm.count ("rpc_ip")) { getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as ()); + getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as()); } // Override the RPC destination port number @@ -352,6 +353,7 @@ int run (int argc, char** argv) { // VFALCO TODO This should be a short. getConfig ().setRpcPort (vm ["rpc_port"].as ()); + getConfig().overwrite("rpc", "port", vm["rpc_port"].as()); } if (vm.count ("quorum")) diff --git a/src/ripple/app/main/RPCHTTPServer.cpp b/src/ripple/app/main/RPCHTTPServer.cpp index 2c8567dea..37780e4e5 100644 --- a/src/ripple/app/main/RPCHTTPServer.cpp +++ b/src/ripple/app/main/RPCHTTPServer.cpp @@ -38,9 +38,11 @@ public: RPCServerHandler m_deprecatedHandler; HTTP::Server m_server; std::unique_ptr m_context; + RPC::Setup setup_; RPCHTTPServerImp (Stoppable& parent, JobQueue& jobQueue, - NetworkOPs& networkOPs, Resource::Manager& resourceManager) + NetworkOPs& networkOPs, Resource::Manager& resourceManager, + RPC::Setup const& setup) : RPCHTTPServer (parent) , m_resourceManager (resourceManager) , m_journal (deprecatedLogs().journal("HTTP-RPC")) @@ -48,18 +50,13 @@ public: , m_networkOPs (networkOPs) , m_deprecatedHandler (networkOPs, resourceManager) , m_server (*this, deprecatedLogs().journal("HTTP")) + , setup_ (setup) { - if (getConfig ().RPC_SECURE == 0) - { - m_context.reset (RippleSSLContext::createBare ()); - } - else - { + if (setup_.secure) m_context.reset (RippleSSLContext::createAuthenticated ( - getConfig ().RPC_SSL_KEY, - getConfig ().RPC_SSL_CERT, - getConfig ().RPC_SSL_CHAIN)); - } + setup_.ssl_key, setup_.ssl_cert, setup_.ssl_chain)); + else + m_context.reset (RippleSSLContext::createBare()); } ~RPCHTTPServerImp() @@ -70,10 +67,9 @@ public: void setup (beast::Journal journal) override { - if (! getConfig ().getRpcIP().empty () && - getConfig ().getRpcPort() != 0) + if (! setup_.ip.empty() && setup_.port != 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 //if (! is_unspecified (ep)) @@ -81,8 +77,8 @@ public: HTTP::Port port; port.security = HTTP::Port::Security::allow_ssl; port.addr = ep.at_port(0); - if (getConfig ().getRpcPort() != 0) - port.port = getConfig ().getRpcPort(); + if (setup_.port != 0) + port.port = setup_.port; else port.port = ep.port(); port.context = m_context.get (); @@ -123,7 +119,7 @@ public: onAccept (HTTP::Session& session) override { // 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())) { session.close (false); @@ -295,10 +291,11 @@ RPCHTTPServer::RPCHTTPServer (Stoppable& parent) std::unique_ptr 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 ( - parent, jobQueue, networkOPs, resourceManager); + parent, jobQueue, networkOPs, resourceManager, setup); } } diff --git a/src/ripple/app/main/RPCHTTPServer.h b/src/ripple/app/main/RPCHTTPServer.h index 51e5295f4..4e1a66f93 100644 --- a/src/ripple/app/main/RPCHTTPServer.h +++ b/src/ripple/app/main/RPCHTTPServer.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED #define RIPPLE_APP_RPCHTTPSERVER_H_INCLUDED +#include #include #include #include // @@ -48,7 +49,8 @@ public: std::unique_ptr make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue, - NetworkOPs& networkOPs, Resource::Manager& resourceManager); + NetworkOPs& networkOPs, Resource::Manager& resourceManager, + RPC::Setup const& setup); } // ripple diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h index db72e91d2..5b27e3505 100644 --- a/src/ripple/core/Config.h +++ b/src/ripple/core/Config.h @@ -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: void 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); void setup (std::string const& strConf, bool bQuiet); void load (); + +private: + void build_legacy(); }; 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 #endif diff --git a/src/ripple/core/Section.h b/src/ripple/core/Section.h index fc6cb0469..5c4006f09 100644 --- a/src/ripple/core/Section.h +++ b/src/ripple/core/Section.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,32 @@ public: /** Create an empty section. */ 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 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. Parsable key/value pairs are also added to the map. */ @@ -57,6 +84,10 @@ public: */ std::pair find (std::string const& name) const; + + friend + std::ostream& + operator<< (std::ostream&, Section const& section); }; /** Set a value from a configuration Section diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index cd96868bb..cfe3a1fe8 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,10 @@ #include #include +#ifndef DUMP_CONFIG +#define DUMP_CONFIG 0 +#endif + namespace ripple { // @@ -237,17 +242,48 @@ BasicConfig::section (std::string const& name) const 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 BasicConfig::build (IniFileSections const& ifs) { for (auto const& entry : ifs) { - auto const result = map_.insert (std::make_pair ( - entry.first, Section{})); + auto const result = map_.emplace (entry.first, Section{}); 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) @@ -458,6 +494,7 @@ void Config::load () std::string strTemp; build (secConfig); + build_legacy(); // XXX Leak IniFileSections::mapped_type* smtTmp; @@ -973,4 +1010,55 @@ beast::File const& Config::getModuleDatabasePath () 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 diff --git a/src/ripple/core/impl/Section.cpp b/src/ripple/core/impl/Section.cpp index 8356223aa..d144efe25 100644 --- a/src/ripple/core/impl/Section.cpp +++ b/src/ripple/core/impl/Section.cpp @@ -19,11 +19,20 @@ #include #include +#include namespace ripple { void -Section::append (std::vector 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) { // '=' static boost::regex const re1 ( @@ -38,25 +47,18 @@ Section::append (std::vector const& lines) , 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 const& lines) +{ lines_.reserve (lines_.size() + lines.size()); - for (auto const& line : lines) - { - 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 - } - } + std::for_each (lines.begin(), lines.end(), + [&](std::string const& line) { this->append (line); }); } bool @@ -74,4 +76,14 @@ Section::find (std::string const& name) const 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