diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 85eb041d67..d5d4cfe960 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -148,6 +148,12 @@
true
true
+
+ true
+ true
+ true
+ true
+
@@ -1352,6 +1358,7 @@
+
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index e595901f8b..efa79c1ec1 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -849,6 +849,9 @@
[1] Ripple\ripple_app\_network
+
+ [1] Ripple\ripple_basio\boost
+
@@ -1584,6 +1587,9 @@
[1] Ripple\ripple_app\_peers
+
+ [1] Ripple\ripple_basio\boost
+
diff --git a/TODO.txt b/TODO.txt
index a0590091a3..2f4756596f 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -2,6 +2,10 @@
RIPPLE TODO
--------------------------------------------------------------------------------
+- See if UniqueNodeList is really used, and if its not used remove it. If
+ only some small part of it is used, then delete the rest. David says
+ that it is broken anyway.
+
- Roll a simple wrapper for sqlite relational stuff like loading the UNL
Completely hide the specifics of SQLite and/or beast::db
@@ -264,3 +268,29 @@ A node is "full below" if we believe we have (either in the database or
The fullBelowCache is a cache of hashes of nodes that are full below. Which means
there are no missing children
+
+What we want from the unique node list:
+ - Some number of trusted roots (known by domain)
+ probably organizations whose job is to provide a list of validators
+ - We imagine the IRGA for example would establish some group whose job is to
+ maintain a list of validators. There would be a public list of criteria
+ that they would use to vet the validator. Things like:
+ * Not anonymous
+ * registered business
+ * Physical location
+ * Agree not to cease operations without notice / arbitrarily
+ * Responsive to complaints
+ - Identifiable jurisdiction
+ * Homogeneity in the jurisdiction is a business risk
+ * If all validators are in the same jurisdiction this is a business risk
+ - OpenCoin sets criteria for the organizations
+ - Rippled will ship with a list of trusted root "certificates"
+ In other words this is a list of trusted domains from which the software
+ can contact each trusted root and retrieve a list of "good" validators
+ and then do something with that information
+ - All the validation information would be public, including the broadcast
+ messages.
+ - The goal is to easily identify bad actors and assess network health
+ * Malicious intent
+ * Or, just hardware problems (faulty drive or memory)
+
diff --git a/modules/ripple_basio/boost/ripple_SslContext.cpp b/modules/ripple_basio/boost/ripple_SslContext.cpp
index 482854a02a..da6db5e3dd 100644
--- a/modules/ripple_basio/boost/ripple_SslContext.cpp
+++ b/modules/ripple_basio/boost/ripple_SslContext.cpp
@@ -26,4 +26,85 @@ SslContext::SslContext ()
{
}
+// VFALCO TODO Can we call this function from the ctor of PeerDoor as well?
+// Or can we move the common code to a new function?
+//
+void SslContext::initializeFromFile (
+ boost::asio::ssl::context& context,
+ std::string key_file,
+ std::string cert_file,
+ std::string chain_file)
+{
+ SSL_CTX* sslContext = context.native_handle ();
+
+ context.set_options (boost::asio::ssl::context::default_workarounds |
+ boost::asio::ssl::context::no_sslv2 |
+ boost::asio::ssl::context::single_dh_use);
+
+ bool cert_set = false;
+
+ if (!cert_file.empty ())
+ {
+ boost::system::error_code error;
+ context.use_certificate_file (cert_file, boost::asio::ssl::context::pem, error);
+
+ if (error)
+ throw std::runtime_error ("Unable to use certificate file");
+
+ cert_set = true;
+ }
+
+ if (!chain_file.empty ())
+ {
+ // VFALCO Replace fopen() with RAII
+ FILE* f = fopen (chain_file.c_str (), "r");
+
+ if (!f)
+ throw std::runtime_error ("Unable to open chain file");
+
+ try
+ {
+ while (true)
+ {
+ X509* x = PEM_read_X509 (f, NULL, NULL, NULL);
+
+ if (x == NULL)
+ break;
+
+ if (!cert_set)
+ {
+ if (SSL_CTX_use_certificate (sslContext, x) != 1)
+ throw std::runtime_error ("Unable to get certificate from chain file");
+
+ cert_set = true;
+ }
+ else if (SSL_CTX_add_extra_chain_cert (sslContext, x) != 1)
+ {
+ X509_free (x);
+ throw std::runtime_error ("Unable to add chain certificate");
+ }
+ }
+
+ fclose (f);
+ }
+ catch (...)
+ {
+ fclose (f);
+ throw;
+ }
+ }
+
+ if (!key_file.empty ())
+ {
+ boost::system::error_code error;
+ context.use_private_key_file (key_file, boost::asio::ssl::context::pem, error);
+
+ if (error)
+ throw std::runtime_error ("Unable to use private key file");
+ }
+
+ if (SSL_CTX_check_private_key (sslContext) != 1)
+ throw std::runtime_error ("Private key not valid");
+}
+
}
diff --git a/modules/ripple_basio/boost/ripple_SslContext.h b/modules/ripple_basio/boost/ripple_SslContext.h
index 0dd81a1f94..f19c01f707 100644
--- a/modules/ripple_basio/boost/ripple_SslContext.h
+++ b/modules/ripple_basio/boost/ripple_SslContext.h
@@ -21,6 +21,12 @@ public:
operator boost::asio::ssl::context& ();
+ static void initializeFromFile (
+ boost::asio::ssl::context& context,
+ std::string key_file,
+ std::string cert_file,
+ std::string chain_file);
+
private:
SslContext ();
diff --git a/src/cpp/ripple/PeerDoor.cpp b/src/cpp/ripple/PeerDoor.cpp
index 7424eea3da..34ca3bf1b0 100644
--- a/src/cpp/ripple/PeerDoor.cpp
+++ b/src/cpp/ripple/PeerDoor.cpp
@@ -6,150 +6,102 @@
SETUP_LOG (PeerDoor)
-// PEER_IP, PEER_PORT, PEER_SSL_CIPHER_LIST
-PeerDoor::PeerDoor (
+class PeerDoorImp : public PeerDoor, LeakChecked
+{
+public:
+ PeerDoorImp (std::string const& ip,
+ int port,
+ std::string const& sslCiphers,
+ boost::asio::io_service& io_service)
+ : mAcceptor (
+ io_service,
+ boost::asio::ip::tcp::endpoint (boost::asio::ip::address ().from_string (ip.empty () ? "0.0.0.0" : ip),
+ port))
+ , mCtx (boost::asio::ssl::context::sslv23)
+ , mDelayTimer (io_service)
+ {
+ mCtx.set_options (
+ boost::asio::ssl::context::default_workarounds |
+ boost::asio::ssl::context::no_sslv2 |
+ boost::asio::ssl::context::single_dh_use);
+
+ SSL_CTX_set_tmp_dh_callback (mCtx.native_handle (), handleTmpDh);
+
+ if (SSL_CTX_set_cipher_list (mCtx.native_handle (), sslCiphers.c_str ()) != 1)
+ std::runtime_error ("Error setting cipher list (no valid ciphers).");
+
+ if (! ip.empty () && port != 0)
+ {
+ Log (lsINFO) << "Peer port: " << ip << " " << port;
+ startListening ();
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ boost::asio::ssl::context& getSSLContext ()
+ {
+ return mCtx;
+ }
+
+ //--------------------------------------------------------------------------
+
+ void startListening ()
+ {
+ Peer::pointer new_connection = Peer::New (
+ mAcceptor.get_io_service (),
+ mCtx,
+ getApp().getPeers ().assignPeerId (),
+ true);
+
+ mAcceptor.async_accept (new_connection->getSocket (),
+ boost::bind (&PeerDoorImp::handleConnect, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ //--------------------------------------------------------------------------
+
+ void handleConnect (Peer::pointer new_connection,
+ const boost::system::error_code& error)
+ {
+ bool delay = false;
+
+ if (!error)
+ {
+ new_connection->connected (error);
+ }
+ else
+ {
+ if (error == boost::system::errc::too_many_files_open)
+ delay = true;
+
+ WriteLog (lsERROR, PeerDoor) << error;
+ }
+
+ if (delay)
+ {
+ mDelayTimer.expires_from_now (boost::posix_time::milliseconds (500));
+ mDelayTimer.async_wait (boost::bind (&PeerDoorImp::startListening, this));
+ }
+ else
+ {
+ startListening ();
+ }
+ }
+
+private:
+ boost::asio::ip::tcp::acceptor mAcceptor;
+ boost::asio::ssl::context mCtx;
+ boost::asio::deadline_timer mDelayTimer;
+};
+
+//------------------------------------------------------------------------------
+
+PeerDoor* PeerDoor::New (
std::string const& ip,
int port,
std::string const& sslCiphers,
boost::asio::io_service& io_service)
- : mAcceptor (
- io_service,
- boost::asio::ip::tcp::endpoint (boost::asio::ip::address ().from_string (ip.empty () ? "0.0.0.0" : ip),
- port))
- , mCtx (boost::asio::ssl::context::sslv23)
- , mDelayTimer (io_service)
{
- mCtx.set_options (
- boost::asio::ssl::context::default_workarounds |
- boost::asio::ssl::context::no_sslv2 |
- boost::asio::ssl::context::single_dh_use);
-
- SSL_CTX_set_tmp_dh_callback (mCtx.native_handle (), handleTmpDh);
-
- if (SSL_CTX_set_cipher_list (mCtx.native_handle (), sslCiphers.c_str ()) != 1)
- std::runtime_error ("Error setting cipher list (no valid ciphers).");
-
- if (! ip.empty () && port != 0)
- {
- Log (lsINFO) << "Peer port: " << ip << " " << port;
- startListening ();
- }
+ return new PeerDoorImp (ip, port, sslCiphers, io_service);
}
-
-void PeerDoor::startListening ()
-{
- Peer::pointer new_connection = Peer::New (
- mAcceptor.get_io_service (),
- mCtx,
- getApp().getPeers ().assignPeerId (),
- true);
-
- mAcceptor.async_accept (new_connection->getSocket (),
- boost::bind (&PeerDoor::handleConnect, this, new_connection,
- boost::asio::placeholders::error));
-}
-
-void PeerDoor::handleConnect (Peer::pointer new_connection,
- const boost::system::error_code& error)
-{
- bool delay = false;
-
- if (!error)
- {
- new_connection->connected (error);
- }
- else
- {
- if (error == boost::system::errc::too_many_files_open)
- delay = true;
-
- WriteLog (lsERROR, PeerDoor) << error;
- }
-
- if (delay)
- {
- mDelayTimer.expires_from_now (boost::posix_time::milliseconds (500));
- mDelayTimer.async_wait (boost::bind (&PeerDoor::startListening, this));
- }
- else
- {
- startListening ();
- }
-}
-
-void initSSLContext (boost::asio::ssl::context& context,
- std::string key_file, std::string cert_file, std::string chain_file)
-{
- SSL_CTX* sslContext = context.native_handle ();
-
- context.set_options (boost::asio::ssl::context::default_workarounds |
- boost::asio::ssl::context::no_sslv2 |
- boost::asio::ssl::context::single_dh_use);
-
- bool cert_set = false;
-
- if (!cert_file.empty ())
- {
- boost::system::error_code error;
- context.use_certificate_file (cert_file, boost::asio::ssl::context::pem, error);
-
- if (error)
- throw std::runtime_error ("Unable to use certificate file");
-
- cert_set = true;
- }
-
- if (!chain_file.empty ())
- {
- // VFALCO Replace fopen() with RAII
- FILE* f = fopen (chain_file.c_str (), "r");
-
- if (!f)
- throw std::runtime_error ("Unable to open chain file");
-
- try
- {
- while (true)
- {
- X509* x = PEM_read_X509 (f, NULL, NULL, NULL);
-
- if (x == NULL)
- break;
-
- if (!cert_set)
- {
- if (SSL_CTX_use_certificate (sslContext, x) != 1)
- throw std::runtime_error ("Unable to get certificate from chain file");
-
- cert_set = true;
- }
- else if (SSL_CTX_add_extra_chain_cert (sslContext, x) != 1)
- {
- X509_free (x);
- throw std::runtime_error ("Unable to add chain certificate");
- }
- }
-
- fclose (f);
- }
- catch (...)
- {
- fclose (f);
- throw;
- }
- }
-
- if (!key_file.empty ())
- {
- boost::system::error_code error;
- context.use_private_key_file (key_file, boost::asio::ssl::context::pem, error);
-
- if (error)
- throw std::runtime_error ("Unable to use private key file");
- }
-
- if (SSL_CTX_check_private_key (sslContext) != 1)
- throw std::runtime_error ("Private key not valid");
-}
-
-// vim:ts=4
diff --git a/src/cpp/ripple/PeerDoor.h b/src/cpp/ripple/PeerDoor.h
index 61aa999c24..decaa657ea 100644
--- a/src/cpp/ripple/PeerDoor.h
+++ b/src/cpp/ripple/PeerDoor.h
@@ -4,35 +4,23 @@
*/
//==============================================================================
-#ifndef __PEERDOOR__
-#define __PEERDOOR__
+#ifndef RIPPLE_PEERDOOR_H_INCLUDED
+#define RIPPLE_PEERDOOR_H_INCLUDED
-/*
-Handles incoming connections from other Peers
+/** Handles incoming connections from peers.
*/
-
class PeerDoor : LeakChecked
{
public:
- PeerDoor (std::string const& ip,
- int port,
- std::string const& sslCiphers,
- boost::asio::io_service& io_service);
+ virtual ~PeerDoor () { }
- boost::asio::ssl::context& getSSLContext ()
- {
- return mCtx;
- }
+ static PeerDoor* New (
+ std::string const& ip,
+ int port,
+ std::string const& sslCiphers,
+ boost::asio::io_service& io_service);
-private:
- boost::asio::ip::tcp::acceptor mAcceptor;
- boost::asio::ssl::context mCtx;
- boost::asio::deadline_timer mDelayTimer;
-
- void startListening ();
- void handleConnect (Peer::pointer new_connection, const boost::system::error_code& error);
+ virtual boost::asio::ssl::context& getSSLContext () = 0;
};
#endif
-
-// vim:ts=4
diff --git a/src/cpp/ripple/RPCDoor.cpp b/src/cpp/ripple/RPCDoor.cpp
index 6c7f30cd06..b692d442a0 100644
--- a/src/cpp/ripple/RPCDoor.cpp
+++ b/src/cpp/ripple/RPCDoor.cpp
@@ -6,11 +6,6 @@
SETUP_LOG (RPCDoor)
-// VFALCO TODO Clean up this loose extern
-//
-extern void initSSLContext (boost::asio::ssl::context& context,
- std::string key_file, std::string cert_file, std::string chain_file);
-
RPCDoor::RPCDoor (boost::asio::io_service& io_service, RPCServer::Handler& handler)
: m_rpcServerHandler (handler)
, mAcceptor (io_service,
@@ -21,7 +16,15 @@ RPCDoor::RPCDoor (boost::asio::io_service& io_service, RPCServer::Handler& handl
WriteLog (lsINFO, RPCDoor) << "RPC port: " << theConfig.getRpcAddress().toRawUTF8() << " allow remote: " << theConfig.RPC_ALLOW_REMOTE;
if (theConfig.RPC_SECURE != 0)
- initSSLContext (mSSLContext, theConfig.RPC_SSL_KEY, theConfig.RPC_SSL_CERT, theConfig.RPC_SSL_CHAIN);
+ {
+ // VFALCO TODO This could be a method of theConfig
+ //
+ basio::SslContext::initializeFromFile (
+ mSSLContext,
+ theConfig.RPC_SSL_KEY,
+ theConfig.RPC_SSL_CERT,
+ theConfig.RPC_SSL_CHAIN);
+ }
startListening ();
}
diff --git a/src/cpp/ripple/ripple_Application.cpp b/src/cpp/ripple/ripple_Application.cpp
index 3af4299f67..6103e84e81 100644
--- a/src/cpp/ripple/ripple_Application.cpp
+++ b/src/cpp/ripple/ripple_Application.cpp
@@ -569,7 +569,7 @@ void Application::setup ()
{
try
{
- mPeerDoor = new PeerDoor (
+ mPeerDoor = PeerDoor::New (
theConfig.PEER_IP,
theConfig.PEER_PORT,
theConfig.PEER_SSL_CIPHER_LIST,
diff --git a/src/cpp/ripple/ripple_UniqueNodeList.cpp b/src/cpp/ripple/ripple_UniqueNodeList.cpp
index f5cb0342e5..23a13e8bf2 100644
--- a/src/cpp/ripple/ripple_UniqueNodeList.cpp
+++ b/src/cpp/ripple/ripple_UniqueNodeList.cpp
@@ -91,8 +91,8 @@ private:
public:
UniqueNodeListImp ()
: m_scoreTimer (this)
- , m_fetchTimer (this)
, mFetchActive (0)
+ , m_fetchTimer (this)
{
}
@@ -135,7 +135,7 @@ public:
// This is called when the application is started.
// Get update times and start fetching and scoring as needed.
- void UniqueNodeListImp::start ()
+ void start ()
{
miscLoad ();
@@ -414,7 +414,7 @@ public:
//--------------------------------------------------------------------------
- bool UniqueNodeListImp::nodeLoad (boost::filesystem::path pConfig)
+ bool nodeLoad (boost::filesystem::path pConfig)
{
if (pConfig.empty ())
{
@@ -1084,12 +1084,7 @@ private:
+ boost::posix_time::seconds (secondsFromNow);
// WriteLog (lsTRACE, UniqueNodeList) << str(boost::format("scoreNext: @%s") % mtpScoreNext);
-#if 1
m_scoreTimer.setExpiration (secondsFromNow);
-#else
- mdtScoreTimer.expires_at (mtpScoreNext);
- mdtScoreTimer.async_wait (BIND_TYPE (&UniqueNodeListImp::scoreTimerHandler, this, P_1));
-#endif
}
}
@@ -1281,14 +1276,9 @@ private:
// Fetch needs to happen in the future. Set a timer to wake us.
mtpFetchNext = tpNext;
-#if 1
double const seconds = (tpNext - tpNow).seconds ();
m_fetchTimer.setExpiration (seconds);
-#else
- mdtFetchTimer.expires_at (mtpFetchNext);
- mdtFetchTimer.async_wait (BIND_TYPE (&UniqueNodeListImp::fetchTimerHandler, this, P_1));
-#endif
}
else
{
diff --git a/src/cpp/ripple/ripple_WSHandler.h b/src/cpp/ripple/ripple_WSHandler.h
index b00db9fe6e..583e102962 100644
--- a/src/cpp/ripple/ripple_WSHandler.h
+++ b/src/cpp/ripple/ripple_WSHandler.h
@@ -7,9 +7,6 @@
#ifndef RIPPLE_WSHANDLER_H_INCLUDED
#define RIPPLE_WSHANDLER_H_INCLUDED
-extern void initSSLContext (boost::asio::ssl::context& context,
- std::string key_file, std::string cert_file, std::string chain_file);
-
extern bool serverOkay (std::string& reason);
template
@@ -52,8 +49,11 @@ public:
{
if (theConfig.WEBSOCKET_SECURE != 0)
{
- initSSLContext (*mCtx, theConfig.WEBSOCKET_SSL_KEY,
- theConfig.WEBSOCKET_SSL_CERT, theConfig.WEBSOCKET_SSL_CHAIN);
+ basio::SslContext::initializeFromFile (
+ *mCtx,
+ theConfig.WEBSOCKET_SSL_KEY,
+ theConfig.WEBSOCKET_SSL_CERT,
+ theConfig.WEBSOCKET_SSL_CHAIN);
}
}