Make PeerDoor implementation private

This commit is contained in:
Vinnie Falco
2013-07-10 09:51:04 -07:00
parent 2db798b38f
commit e4c02aa122
11 changed files with 251 additions and 188 deletions

View File

@@ -148,6 +148,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_basio\boost\ripple_SslContext.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_basio\ripple_basio.cpp" />
<ClCompile Include="..\..\modules\ripple_client\ripple_client.cpp" />
<ClCompile Include="..\..\modules\ripple_core\functional\ripple_Config.cpp">
@@ -1352,6 +1358,7 @@
<ClInclude Include="..\..\modules\ripple_basics\utility\ripple_Time.h" />
<ClInclude Include="..\..\modules\ripple_basics\utility\ripple_UptimeTimer.h" />
<ClInclude Include="..\..\modules\ripple_basio\boost\ripple_IoService.h" />
<ClInclude Include="..\..\modules\ripple_basio\boost\ripple_SslContext.h" />
<ClInclude Include="..\..\modules\ripple_basio\ripple_basio.h" />
<ClInclude Include="..\..\modules\ripple_basio\ripple_basio_fwdecl.h" />
<ClInclude Include="..\..\modules\ripple_basio\ripple_basio_impl.h" />

View File

@@ -849,6 +849,9 @@
<ClCompile Include="..\..\src\cpp\ripple\ripple_WSHandler.cpp">
<Filter>[1] Ripple\ripple_app\_network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_basio\boost\ripple_SslContext.cpp">
<Filter>[1] Ripple\ripple_basio\boost</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Subtrees\sqlite\sqlite3.h">
@@ -1584,6 +1587,9 @@
<ClInclude Include="..\..\src\cpp\ripple\ripple_UniqueNodeList.h">
<Filter>[1] Ripple\ripple_app\_peers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_basio\boost\ripple_SslContext.h">
<Filter>[1] Ripple\ripple_basio\boost</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\cpp\ripple\ripple.proto" />

View File

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

View File

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

View File

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

View File

@@ -6,9 +6,10 @@
SETUP_LOG (PeerDoor)
// PEER_IP, PEER_PORT, PEER_SSL_CIPHER_LIST
PeerDoor::PeerDoor (
std::string const& ip,
class PeerDoorImp : public PeerDoor, LeakChecked <PeerDoorImp>
{
public:
PeerDoorImp (std::string const& ip,
int port,
std::string const& sslCiphers,
boost::asio::io_service& io_service)
@@ -18,7 +19,7 @@ PeerDoor::PeerDoor (
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 |
@@ -34,10 +35,19 @@ PeerDoor::PeerDoor (
Log (lsINFO) << "Peer port: " << ip << " " << port;
startListening ();
}
}
}
void PeerDoor::startListening ()
{
//--------------------------------------------------------------------------
boost::asio::ssl::context& getSSLContext ()
{
return mCtx;
}
//--------------------------------------------------------------------------
void startListening ()
{
Peer::pointer new_connection = Peer::New (
mAcceptor.get_io_service (),
mCtx,
@@ -45,13 +55,15 @@ void PeerDoor::startListening ()
true);
mAcceptor.async_accept (new_connection->getSocket (),
boost::bind (&PeerDoor::handleConnect, this, new_connection,
boost::bind (&PeerDoorImp::handleConnect, this, new_connection,
boost::asio::placeholders::error));
}
}
void PeerDoor::handleConnect (Peer::pointer new_connection,
//--------------------------------------------------------------------------
void handleConnect (Peer::pointer new_connection,
const boost::system::error_code& error)
{
{
bool delay = false;
if (!error)
@@ -69,87 +81,27 @@ void PeerDoor::handleConnect (Peer::pointer new_connection,
if (delay)
{
mDelayTimer.expires_from_now (boost::posix_time::milliseconds (500));
mDelayTimer.async_wait (boost::bind (&PeerDoor::startListening, this));
mDelayTimer.async_wait (boost::bind (&PeerDoorImp::startListening, this));
}
else
{
startListening ();
}
}
}
void initSSLContext (boost::asio::ssl::context& context,
std::string key_file, std::string cert_file, std::string chain_file)
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)
{
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");
return new PeerDoorImp (ip, port, sslCiphers, io_service);
}
// vim:ts=4

View File

@@ -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 <PeerDoor>
{
public:
PeerDoor (std::string const& ip,
virtual ~PeerDoor () { }
static PeerDoor* New (
std::string const& ip,
int port,
std::string const& sslCiphers,
boost::asio::io_service& io_service);
boost::asio::ssl::context& getSSLContext ()
{
return mCtx;
}
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

View File

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

View File

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

View File

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

View File

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