Add PROXY peer listener and consolidate SSL contexts.

This commit is contained in:
Vinnie Falco
2013-08-25 00:11:04 -07:00
parent 3602e19dcd
commit 4170bcd294
34 changed files with 947 additions and 832 deletions

View File

@@ -313,24 +313,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\network\ripple_WSHandler.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_app\network\WSConnection.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_app\network\WSDoor.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_app\node\ripple_HyperLevelDBBackendFactory.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -683,8 +665,26 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\websocket\WSConnection.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_app\websocket\WSDoor.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_app\websocket\WSServerHandler.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_asio\ripple_asio.cpp" />
<ClCompile Include="..\..\modules\ripple_asio\sockets\ripple_RippleTlsContext.cpp">
<ClCompile Include="..\..\modules\ripple_asio\sockets\RippleSSLContext.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>
@@ -1421,9 +1421,6 @@
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_ProofOfWorkFactory.h" />
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedLedger.h" />
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedTransaction.h" />
<ClInclude Include="..\..\modules\ripple_app\network\ripple_WSHandler.h" />
<ClInclude Include="..\..\modules\ripple_app\network\WSConnection.h" />
<ClInclude Include="..\..\modules\ripple_app\network\WSDoor.h" />
<ClInclude Include="..\..\modules\ripple_app\node\ripple_HyperLevelDBBackendFactory.h" />
<ClInclude Include="..\..\modules\ripple_app\node\ripple_KeyvaDBBackendFactory.h" />
<ClInclude Include="..\..\modules\ripple_app\node\ripple_MdbBackendFactory.h" />
@@ -1441,7 +1438,7 @@
<ClInclude Include="..\..\modules\ripple_app\paths\ripple_RippleState.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\PeerDoor.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_ClusterNodeStatus.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_IPeers.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_Peers.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_Peer.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_PeerSet.h" />
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_UniqueNodeList.h" />
@@ -1475,11 +1472,14 @@
<ClInclude Include="..\..\modules\ripple_app\tx\Transactor.h" />
<ClInclude Include="..\..\modules\ripple_app\tx\TrustSetTransactor.h" />
<ClInclude Include="..\..\modules\ripple_app\tx\WalletAddTransactor.h" />
<ClInclude Include="..\..\modules\ripple_app\websocket\WSConnection.h" />
<ClInclude Include="..\..\modules\ripple_app\websocket\WSDoor.h" />
<ClInclude Include="..\..\modules\ripple_app\websocket\WSServerHandler.h" />
<ClInclude Include="..\..\modules\ripple_asio\ripple_asio.h" />
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_MultiSocket.cpp" />
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_MultiSocket.h" />
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_MultiSocketType.h" />
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_RippleTlsContext.h" />
<ClInclude Include="..\..\modules\ripple_asio\sockets\RippleSSLContext.h" />
<ClInclude Include="..\..\modules\ripple_basics\containers\ripple_KeyCache.h" />
<ClInclude Include="..\..\modules\ripple_basics\containers\ripple_RangeSet.h" />
<ClInclude Include="..\..\modules\ripple_basics\containers\ripple_SecureAllocator.h" />

View File

@@ -124,9 +124,6 @@
<Filter Include="[1] Ripple\ripple_app\misc">
<UniqueIdentifier>{29393027-f1ed-4700-bbd1-c880091ab96b}</UniqueIdentifier>
</Filter>
<Filter Include="[1] Ripple\ripple_app\network">
<UniqueIdentifier>{7c14e9df-6d8d-4ba3-b208-f89c1d0b6b30}</UniqueIdentifier>
</Filter>
<Filter Include="[1] Ripple\ripple_app\paths">
<UniqueIdentifier>{66d2d40a-72bd-41f5-9cf9-1f464a40bb04}</UniqueIdentifier>
</Filter>
@@ -160,6 +157,9 @@
<Filter Include="[1] Ripple\ripple_app\boost">
<UniqueIdentifier>{8476f6e8-7411-460f-bdef-68e3166078eb}</UniqueIdentifier>
</Filter>
<Filter Include="[1] Ripple\ripple_app\websocket">
<UniqueIdentifier>{7c14e9df-6d8d-4ba3-b208-f89c1d0b6b30}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\Subtrees\beast\modules\beast_core\beast_core.cpp">
@@ -714,15 +714,6 @@
<ClCompile Include="..\..\modules\ripple_app\misc\NetworkOPs.cpp">
<Filter>[1] Ripple\ripple_app\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\network\WSConnection.cpp">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\network\WSDoor.cpp">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\network\ripple_WSHandler.cpp">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\paths\ripple_Pathfinder.cpp">
<Filter>[1] Ripple\ripple_app\paths</Filter>
</ClCompile>
@@ -873,9 +864,6 @@
<ClCompile Include="..\..\modules\ripple_asio\ripple_asio.cpp">
<Filter>[1] Ripple\ripple_asio</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_asio\sockets\ripple_RippleTlsContext.cpp">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\boost\ripple_IoService.cpp">
<Filter>[1] Ripple\ripple_app\boost</Filter>
</ClCompile>
@@ -885,6 +873,18 @@
<ClCompile Include="..\..\Subtrees\beast\modules\beast_boost\beast_boost.cpp">
<Filter>[0] Subtrees\beast</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_asio\sockets\RippleSSLContext.cpp">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\websocket\WSConnection.cpp">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\websocket\WSDoor.cpp">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_app\websocket\WSServerHandler.cpp">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\modules\ripple_app\ripple_app.h">
@@ -1499,15 +1499,6 @@
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedTransaction.h">
<Filter>[1] Ripple\ripple_app\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\network\ripple_WSHandler.h">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\network\WSConnection.h">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\network\WSDoor.h">
<Filter>[1] Ripple\ripple_app\network</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\paths\ripple_Pathfinder.h">
<Filter>[1] Ripple\ripple_app\paths</Filter>
</ClInclude>
@@ -1529,9 +1520,6 @@
<ClInclude Include="..\..\modules\ripple_app\peers\PeerDoor.h">
<Filter>[1] Ripple\ripple_app\peers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_IPeers.h">
<Filter>[1] Ripple\ripple_app\peers</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_Peer.h">
<Filter>[1] Ripple\ripple_app\peers</Filter>
</ClInclude>
@@ -1658,9 +1646,6 @@
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_MultiSocket.h">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_RippleTlsContext.h">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_asio\sockets\ripple_MultiSocket.cpp">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClInclude>
@@ -1676,6 +1661,21 @@
<ClInclude Include="..\..\modules\ripple_basics\utility\ripple_LoggedTimings.h">
<Filter>[1] Ripple\ripple_basics\utility</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_asio\sockets\RippleSSLContext.h">
<Filter>[1] Ripple\ripple_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\websocket\WSConnection.h">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\websocket\WSDoor.h">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\websocket\WSServerHandler.h">
<Filter>[1] Ripple\ripple_app\websocket</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\ripple_app\peers\ripple_Peers.h">
<Filter>[1] Ripple\ripple_app\peers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\modules\ripple_data\protocol\ripple.proto">

View File

@@ -64,15 +64,13 @@ public:
return boost::asio::ssl::stream_base::client;
}
}
// TLS policy adds the on_tls_init method to the handler to allow the user
// to set up their asio TLS context.
class handler_interface {
public:
virtual ~handler_interface() {}
virtual void on_tcp_init() {};
virtual boost::shared_ptr<boost::asio::ssl::context> on_tls_init() = 0;
virtual boost::asio::ssl::context& get_ssl_context () = 0;
};
// Connection specific details
@@ -97,15 +95,12 @@ public:
, m_connection(static_cast< connection_type& >(*this)) {}
void init() {
m_context_ptr = m_connection.get_handler()->on_tls_init();
boost::asio::ssl::context& ssl_context (
m_connection.get_handler()->get_ssl_context());
if (!m_context_ptr) {
throw "handler was unable to init autotls, connection error";
}
m_socket_ptr =
autotls_socket_ptr(new autotls_socket(m_endpoint.get_io_service(), *m_context_ptr,
m_endpoint.m_secure_only, m_endpoint.m_plain_only));
m_socket_ptr = autotls_socket_ptr (new autotls_socket (
m_endpoint.get_io_service(), ssl_context, m_endpoint.m_secure_only,
m_endpoint.m_plain_only));
}
void async_init(boost::function<void(const boost::system::error_code&)> callback)

View File

@@ -70,14 +70,12 @@ public:
return true;
}
// TLS policy adds the on_tls_init method to the handler to allow the user
// to set up their asio TLS context.
class handler_interface {
public:
virtual ~handler_interface() {}
virtual void on_tcp_init() {};
virtual boost::shared_ptr<boost::asio::ssl::context> on_tls_init() = 0;
virtual boost::asio::ssl::context& on_tls_init() = 0;
};
// Connection specific details
@@ -101,14 +99,13 @@ public:
: m_endpoint(e)
, m_connection(static_cast< connection_type& >(*this)) {}
void init() {
m_context_ptr = m_connection.get_handler()->on_tls_init();
if (!m_context_ptr) {
throw "handler was unable to init tls, connection error";
}
m_socket_ptr = tls_socket_ptr(new tls_socket(m_endpoint.get_io_service(),*m_context_ptr));
void init()
{
boost::asio::ssl::context& ssl_context (
m_connection.get_handler()->get_ssl_context ());
m_socket_ptr = tls_socket_ptr (new tls_socket (
m_endpoint.get_io_service(), ssl_context));
}
void async_init(boost::function<void(const boost::system::error_code&)> callback)

View File

@@ -175,7 +175,6 @@ public:
, mValidations (IValidations::New ())
, mUNL (UniqueNodeList::New ())
, mProofOfWorkFactory (IProofOfWorkFactory::New ())
, mPeers (IPeers::New (m_mainService))
, m_loadManager (ILoadManager::New ())
// VFALCO End new stuff
// VFALCO TODO replace all NULL with nullptr
@@ -183,10 +182,7 @@ public:
, mTxnDB (NULL)
, mLedgerDB (NULL)
, mWalletDB (NULL) // VFALCO NOTE are all these 'NULL' ctor params necessary?
, mPeerDoor (NULL)
, mRPCDoor (NULL)
, mWSPublicDoor (NULL)
, mWSPrivateDoor (NULL)
, mSweepTimer (m_auxService)
, mShutdown (false)
{
@@ -283,7 +279,7 @@ public:
PeerDoor& getPeerDoor ()
{
return *mPeerDoor;
return *m_peerDoor;
}
OrderBookDB& getOrderBookDB ()
@@ -336,9 +332,9 @@ public:
return *mProofOfWorkFactory;
}
IPeers& getPeers ()
Peers& getPeers ()
{
return *mPeers;
return *m_peers;
}
// VFALCO TODO Move these to the .cpp
@@ -519,25 +515,54 @@ public:
mLedgerMaster.setMinValidations (getConfig ().VALIDATION_QUORUM);
//----------------------------------------------------------------------
//
// Allow peer connections.
//
// SSL context used for Peer connections.
{
m_peerSSLContext = RippleSSLContext::createAnonymous (
getConfig ().PEER_SSL_CIPHER_LIST);
// VFALCO NOTE, It seems the WebSocket context never has
// set_verify_mode called, for either setting of WEBSOCKET_SECURE
m_peerSSLContext->get().set_verify_mode (boost::asio::ssl::verify_none);
}
// VFALCO NOTE Unfortunately, in stand-alone mode some code still
// foolishly calls getPeers(). When this is fixed we can move
// the creation of the peer SSL context and Peers object into
// the conditional.
//
m_peers = Peers::New (m_mainService, m_peerSSLContext->get ());
// If we're not in standalone mode,
// prepare ourselves for networking
//
if (!getConfig ().RUN_STANDALONE)
{
try
{
mPeerDoor = PeerDoor::New (
getConfig ().PEER_IP,
getConfig ().PEER_PORT,
getConfig ().PEER_SSL_CIPHER_LIST,
m_mainService);
}
catch (const std::exception& e)
{
// Must run as directed or exit.
WriteLog (lsFATAL, Application) << boost::str (boost::format ("Can not open peer service: %s") % e.what ());
// Create the listening sockets for peers
//
m_peerDoor = PeerDoor::New (
PeerDoor::sslRequired,
getConfig ().PEER_IP,
getConfig ().peerListeningPort,
m_mainService,
m_peerSSLContext->get ());
exit (3);
if (getConfig ().peerPROXYListeningPort != 0)
{
#if RIPPLE_PEER_USES_BEAST_MULTISOCKET
// Also listen on a PROXY-only port.
m_peerProxyDoor = PeerDoor::New (
PeerDoor::sslAndPROXYRequired,
getConfig ().PEER_IP,
getConfig ().peerPROXYListeningPort,
m_mainService,
m_peerSSLContext->get ());
#else
WriteLog (lsWARNING, Application) << "Peer PROXY interface: configured but disabled by build configuration.";
#endif
}
}
else
@@ -545,6 +570,59 @@ public:
WriteLog (lsINFO, Application) << "Peer interface: disabled";
}
// SSL context used for WebSocket connections.
if (getConfig ().WEBSOCKET_SECURE)
{
m_wsSSLContext = RippleSSLContext::createAuthenticated (
getConfig ().WEBSOCKET_SSL_KEY,
getConfig ().WEBSOCKET_SSL_CERT,
getConfig ().WEBSOCKET_SSL_CHAIN);
}
else
{
m_wsSSLContext = RippleSSLContext::createBare ();
}
// Create private listening WebSocket socket
//
if (!getConfig ().WEBSOCKET_IP.empty () && getConfig ().WEBSOCKET_PORT)
{
m_wsPrivateDoor = WSDoor::New (getConfig ().WEBSOCKET_IP,
getConfig ().WEBSOCKET_PORT, false, m_wsSSLContext->get ());
if (m_wsPrivateDoor == nullptr)
{
FatalError ("Could not open the WebSocket private interface.",
__FILE__, __LINE__);
}
}
else
{
WriteLog (lsINFO, Application) << "WebSocket private interface: disabled";
}
// Create public listening WebSocket socket
//
if (!getConfig ().WEBSOCKET_PUBLIC_IP.empty () && getConfig ().WEBSOCKET_PUBLIC_PORT)
{
m_wsPublicDoor = WSDoor::New (getConfig ().WEBSOCKET_PUBLIC_IP,
getConfig ().WEBSOCKET_PUBLIC_PORT, true, m_wsSSLContext->get ());
if (m_wsPublicDoor == nullptr)
{
FatalError ("Could not open the WebSocket public interface.",
__FILE__, __LINE__);
}
}
else
{
WriteLog (lsINFO, Application) << "WebSocket public interface: disabled";
}
//
//
//----------------------------------------------------------------------
//
// Allow RPC connections.
//
@@ -567,55 +645,11 @@ public:
WriteLog (lsINFO, Application) << "RPC interface: disabled";
}
//
// Allow private WS connections.
//
if (!getConfig ().WEBSOCKET_IP.empty () && getConfig ().WEBSOCKET_PORT)
{
try
{
mWSPrivateDoor = new WSDoor (getConfig ().WEBSOCKET_IP, getConfig ().WEBSOCKET_PORT, false);
}
catch (const std::exception& e)
{
// Must run as directed or exit.
WriteLog (lsFATAL, Application) << boost::str (boost::format ("Can not open private websocket service: %s") % e.what ());
exit (3);
}
}
else
{
WriteLog (lsINFO, Application) << "WS private interface: disabled";
}
//
// Allow public WS connections.
//
if (!getConfig ().WEBSOCKET_PUBLIC_IP.empty () && getConfig ().WEBSOCKET_PUBLIC_PORT)
{
try
{
mWSPublicDoor = new WSDoor (getConfig ().WEBSOCKET_PUBLIC_IP, getConfig ().WEBSOCKET_PUBLIC_PORT, true);
}
catch (const std::exception& e)
{
// Must run as directed or exit.
WriteLog (lsFATAL, Application) << boost::str (boost::format ("Can not open public websocket service: %s") % e.what ());
exit (3);
}
}
else
{
WriteLog (lsINFO, Application) << "WS public interface: disabled";
}
//
// Begin connecting to network.
//
if (!getConfig ().RUN_STANDALONE)
mPeers->start ();
m_peers->start ();
if (getConfig ().RUN_STANDALONE)
{
@@ -631,7 +665,6 @@ public:
}
}
void run ();
void stop ();
void sweep ();
@@ -648,10 +681,6 @@ private:
IoServiceThread m_mainService;
IoServiceThread m_auxService;
//boost::asio::io_service mIOService;
//boost::asio::io_service mAuxService;
//boost::asio::io_service::work mIOWork;
LocalCredentials m_localCredentials;
LedgerMaster mLedgerMaster;
InboundLedgers m_inboundLedgers;
@@ -666,6 +695,8 @@ private:
OrderBookDB mOrderBookDB;
// VFALCO Clean stuff
ScopedPointer <SSLContext> m_peerSSLContext;
ScopedPointer <SSLContext> m_wsSSLContext;
ScopedPointer <NodeStore> m_nodeStore;
ScopedPointer <Validators> m_validators;
ScopedPointer <IFeatures> mFeatures;
@@ -675,8 +706,12 @@ private:
ScopedPointer <IValidations> mValidations;
ScopedPointer <UniqueNodeList> mUNL;
ScopedPointer <IProofOfWorkFactory> mProofOfWorkFactory;
ScopedPointer <IPeers> mPeers;
ScopedPointer <Peers> m_peers;
ScopedPointer <ILoadManager> m_loadManager;
ScopedPointer <PeerDoor> m_peerDoor;
ScopedPointer <PeerDoor> m_peerProxyDoor;
ScopedPointer <WSDoor> m_wsPublicDoor;
ScopedPointer <WSDoor> m_wsPrivateDoor;
// VFALCO End Clean stuff
DatabaseCon* mRpcDB;
@@ -684,10 +719,7 @@ private:
DatabaseCon* mLedgerDB;
DatabaseCon* mWalletDB;
ScopedPointer <PeerDoor> mPeerDoor;
ScopedPointer <RPCDoor> mRPCDoor;
ScopedPointer <WSDoor> mWSPublicDoor;
ScopedPointer <WSDoor> mWSPrivateDoor;
boost::asio::deadline_timer mSweepTimer;
@@ -700,6 +732,7 @@ private:
void ApplicationImp::stop ()
{
WriteLog (lsINFO, Application) << "Received shutdown request";
StopSustain ();
mShutdown = true;
m_mainService.stop ();
@@ -715,43 +748,56 @@ void ApplicationImp::stop ()
void ApplicationImp::run ()
{
// VFALCO TODO The unit tests crash if we try to
// run these threads in the IoService constructor
// so this hack makes them start later.
//
m_mainService.runExtraThreads ();
m_auxService.runExtraThreads ();
if (!getConfig ().RUN_STANDALONE)
{
// VFALCO NOTE This seems unnecessary. If we properly refactor the load
// manager then the deadlock detector can just always be "armed"
// VFALCO TODO The unit tests crash if we try to
// run these threads in the IoService constructor
// so this hack makes them start later.
//
getApp().getLoadManager ().activateDeadlockDetector ();
m_mainService.runExtraThreads ();
m_auxService.runExtraThreads ();
if (!getConfig ().RUN_STANDALONE)
{
// VFALCO NOTE This seems unnecessary. If we properly refactor the load
// manager then the deadlock detector can just always be "armed"
//
getApp().getLoadManager ().activateDeadlockDetector ();
}
}
m_mainService.run (); // This blocks until the io_service is stopped.
if (mWSPublicDoor)
mWSPublicDoor->stop ();
if (mWSPrivateDoor)
mWSPrivateDoor->stop ();
// VFALCO TODO Try to not have to do this early, by using observers to
// eliminate LoadManager's dependency inversions.
//--------------------------------------------------------------------------
//
//
// This deletes the object and therefore, stops the thread.
m_loadManager = nullptr;
mSweepTimer.cancel();
// We use the main thread to call io_service::run.
// What else would we have it do? It blocks until the server
// eventually gets a stop command.
//
m_mainService.run ();
WriteLog (lsINFO, Application) << "Done.";
//
//
//--------------------------------------------------------------------------
// VFALCO NOTE This is a sign that something is wrong somewhere, it
// shouldn't be necessary to sleep until some flag is set.
while (mShutdown)
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
{
m_wsPublicDoor = nullptr;
m_wsPrivateDoor = nullptr;
// VFALCO TODO Try to not have to do this early, by using observers to
// eliminate LoadManager's dependency inversions.
//
// This deletes the object and therefore, stops the thread.
m_loadManager = nullptr;
mSweepTimer.cancel();
WriteLog (lsINFO, Application) << "Done.";
// VFALCO NOTE This is a sign that something is wrong somewhere, it
// shouldn't be necessary to sleep until some flag is set.
while (mShutdown)
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
}
}
void ApplicationImp::sweep ()

View File

@@ -12,7 +12,7 @@ class IFeatures;
class IFeeVote;
class IHashRouter;
class ILoadFeeTrack;
class IPeers;
class Peers;
class IProofOfWorkFactory;
class UniqueNodeList;
class IValidations;
@@ -83,12 +83,12 @@ public:
virtual IHashRouter& getHashRouter () = 0;
virtual ILoadFeeTrack& getFeeTrack () = 0;
virtual ILoadManager& getLoadManager () = 0;
virtual IPeers& getPeers () = 0;
virtual Peers& getPeers () = 0;
virtual IProofOfWorkFactory& getProofOfWorkFactory () = 0;
virtual UniqueNodeList& getUNL () = 0;
virtual UniqueNodeList& getUNL () = 0;
virtual IValidations& getValidations () = 0;
virtual NodeStore& getNodeStore () = 0;
virtual NodeStore& getNodeStore () = 0;
virtual JobQueue& getJobQueue () = 0;
virtual InboundLedgers& getInboundLedgers () = 0;
virtual LedgerMaster& getLedgerMaster () = 0;

View File

@@ -4,9 +4,9 @@
*/
//==============================================================================
LocalCredentials::LocalCredentials () : mDh512 (NULL), mDh1024 (NULL), mLedger (0)
LocalCredentials::LocalCredentials ()
: mLedger (0)
{
;
}
void LocalCredentials::start ()
@@ -32,7 +32,6 @@ void LocalCredentials::start ()
// Retrieve network identity.
bool LocalCredentials::nodeIdentityLoad ()
{
Database* db = getApp().getWalletDB ()->getDB ();
DeprecatedScopedLock sl (getApp().getWalletDB ()->getDBLock ());
bool bSuccess = false;
@@ -47,9 +46,6 @@ bool LocalCredentials::nodeIdentityLoad ()
mNodePublicKey.setNodePublic (strPublicKey);
mNodePrivateKey.setNodePrivate (strPrivateKey);
mDh512 = DH_der_load (db->getStrBinary ("Dh512"));
mDh1024 = DH_der_load (db->getStrBinary ("Dh1024"));
db->endIterRows ();
bSuccess = true;
}
@@ -77,22 +73,12 @@ bool LocalCredentials::nodeIdentityCreate ()
RippleAddress naNodePrivate = RippleAddress::createNodePrivate (naSeed);
// Make new key.
#ifdef CREATE_NEW_DH_PARAMS
std::string strDh512 = DH_der_gen (512);
#else
static const unsigned char dh512Param[] =
{
0x30, 0x46, 0x02, 0x41, 0x00, 0x98, 0x15, 0xd2, 0xd0, 0x08, 0x32, 0xda,
0xaa, 0xac, 0xc4, 0x71, 0xa3, 0x1b, 0x11, 0xf0, 0x6c, 0x62, 0xb2, 0x35,
0x8a, 0x10, 0x92, 0xc6, 0x0a, 0xa3, 0x84, 0x7e, 0xaf, 0x17, 0x29, 0x0b,
0x70, 0xef, 0x07, 0x4f, 0xfc, 0x9d, 0x6d, 0x87, 0x99, 0x19, 0x09, 0x5b,
0x6e, 0xdb, 0x57, 0x72, 0x4a, 0x7e, 0xcd, 0xaf, 0xbd, 0x3a, 0x97, 0x55,
0x51, 0x77, 0x5a, 0x34, 0x7c, 0xe8, 0xc5, 0x71, 0x63, 0x02, 0x01, 0x02
};
std::string strDh512 (reinterpret_cast<const char*> (dh512Param), sizeof (dh512Param));
#endif
std::string strDh512 = DH_der_gen (512);
#else
std::string strDh512 (RippleSSLContext::getRawDHParams (512));
#endif
#if 1
std::string strDh1024 = strDh512; // For testing and most cases 512 is fine.

View File

@@ -28,16 +28,6 @@ public:
return mNodePrivateKey;
}
DH* getDh512 () const
{
return DHparams_dup (mDh512);
}
DH* getDh1024 () const
{
return DHparams_dup (mDh1024);
}
// Local persistence of RPC clients
bool dataDelete (std::string const& strKey);
@@ -57,8 +47,6 @@ private:
RippleAddress mNodePublicKey;
RippleAddress mNodePrivateKey;
DH* mDh512;
DH* mDh1024;
LedgerIndex mLedger; // ledger we last synched to
};

View File

@@ -1,117 +0,0 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
SETUP_LOG (WSDoor)
//
// This is a light weight, untrusted interface for web clients.
// For now we don't provide proof. Later we will.
//
// Might need to support this header for browsers: Access-Control-Allow-Origin: *
// - https://developer.mozilla.org/en-US/docs/HTTP_access_control
//
//
// Strategy:
// - We only talk to NetworkOPs (so we will work even in thin mode)
// - NetworkOPs is smart enough to subscribe and or pass back messages
//
// VFALCO NOTE NetworkOPs isn't used here...
//
WSDoor::WSDoor (std::string const& strIp, int iPort, bool bPublic)
: Thread ("websocket")
, m_endpointLock (this, "WSDoor", __FILE__, __LINE__)
, mPublic (bPublic)
, mIp (strIp)
, mPort (iPort)
{
startThread ();
}
WSDoor::~WSDoor ()
{
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
if (m_endpoint != nullptr)
m_endpoint->stop ();
}
signalThreadShouldExit ();
waitForThreadToExit ();
}
void WSDoor::run ()
{
WriteLog (lsINFO, WSDoor) << boost::str (boost::format ("Websocket: %s: Listening: %s %d ")
% (mPublic ? "Public" : "Private")
% mIp
% mPort);
// Generate a single SSL context for use by all connections.
boost::shared_ptr<boost::asio::ssl::context> mCtx;
mCtx = boost::make_shared<boost::asio::ssl::context> (boost::asio::ssl::context::sslv23);
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);
websocketpp::server_autotls::handler::ptr handler (new WSServerHandler<websocketpp::server_autotls> (mCtx, mPublic));
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
m_endpoint = new websocketpp::server_autotls (handler);
}
// mEndpoint->alog().unset_level(websocketpp::log::alevel::ALL);
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
// Call the main-event-loop of the websocket server.
try
{
m_endpoint->listen (
boost::asio::ip::tcp::endpoint (
boost::asio::ip::address ().from_string (mIp), mPort));
}
catch (websocketpp::exception& e)
{
WriteLog (lsWARNING, WSDoor) << "websocketpp exception: " << e.what ();
while (1) // temporary workaround for websocketpp throwing exceptions on access/close races
{
// https://github.com/zaphoyd/websocketpp/issues/98
try
{
m_endpoint->get_io_service ().run ();
break;
}
catch (websocketpp::exception& e)
{
WriteLog (lsWARNING, WSDoor) << "websocketpp exception: " << e.what ();
}
}
}
delete m_endpoint;
}
void WSDoor::stop ()
{
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
if (m_endpoint != nullptr)
m_endpoint->stop ();
}
signalThreadShouldExit ();
waitForThreadToExit ();
}

View File

@@ -1,35 +0,0 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_WSDOOR_RIPPLEHEADER
#define RIPPLE_WSDOOR_RIPPLEHEADER
class WSDoor : protected Thread, LeakChecked <WSDoor>
{
public:
WSDoor (std::string const& strIp, int iPort, bool bPublic);
~WSDoor ();
void stop ();
private:
void run ();
private:
typedef RippleRecursiveMutex LockType;
typedef LockType::ScopedLockType ScopedLockType;
LockType m_endpointLock;
ScopedPointer <websocketpp::server_autotls> m_endpoint;
bool mPublic;
std::string mIp;
int mPort;
};
#endif
// vim:ts=4

View File

@@ -9,27 +9,14 @@ SETUP_LOG (PeerDoor)
class PeerDoorImp : public PeerDoor, LeakChecked <PeerDoorImp>
{
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)
PeerDoorImp (Kind kind, std::string const& ip, int port,
boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
: m_kind (kind)
, m_ssl_context (ssl_context)
, mAcceptor (io_service, boost::asio::ip::tcp::endpoint (
boost::asio::ip::address ().from_string (ip.empty () ? "0.0.0.0" : ip), port))
, 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;
@@ -39,30 +26,25 @@ public:
//--------------------------------------------------------------------------
boost::asio::ssl::context& getSSLContext ()
{
return mCtx;
}
//--------------------------------------------------------------------------
void startListening ()
{
Peer::pointer new_connection = Peer::New (
mAcceptor.get_io_service (),
mCtx,
getApp().getPeers ().assignPeerId (),
true);
bool const isInbound (true);
bool const requirePROXYHandshake (m_kind == sslAndPROXYRequired);
Peer::pointer new_connection (Peer::New (
mAcceptor.get_io_service (), m_ssl_context,
getApp().getPeers ().assignPeerId (),
isInbound, requirePROXYHandshake));
mAcceptor.async_accept (new_connection->getNativeSocket (),
boost::bind (&PeerDoorImp::handleConnect, this, new_connection,
boost::asio::placeholders::error));
boost::bind (&PeerDoorImp::handleConnect, this, new_connection,
boost::asio::placeholders::error));
}
//--------------------------------------------------------------------------
void handleConnect (Peer::pointer new_connection,
const boost::system::error_code& error)
boost::system::error_code const& error)
{
bool delay = false;
@@ -90,18 +72,16 @@ public:
}
private:
Kind m_kind;
boost::asio::ssl::context& m_ssl_context;
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)
PeerDoor* PeerDoor::New (Kind kind, std::string const& ip, int port,
boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
{
return new PeerDoorImp (ip, port, sslCiphers, io_service);
return new PeerDoorImp (kind, ip, port, io_service, ssl_context);
}

View File

@@ -14,13 +14,16 @@ class PeerDoor : LeakChecked <PeerDoor>
public:
virtual ~PeerDoor () { }
static PeerDoor* New (
std::string const& ip,
int port,
std::string const& sslCiphers,
boost::asio::io_service& io_service);
enum Kind
{
sslRequired,
sslAndPROXYRequired
};
virtual boost::asio::ssl::context& getSSLContext () = 0;
static PeerDoor* New (Kind kind, std::string const& ip, int port,
boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context);
//virtual boost::asio::ssl::context& getSSLContext () = 0;
};
#endif

View File

@@ -33,22 +33,22 @@ public:
//
#if RIPPLE_PEER_USES_BEAST_MULTISOCKET
ScopedPointer <MultiSocket> m_multiSocket;
ScopedPointer <MultiSocket> m_socket;
boost::asio::io_service& m_strand;
NativeSocketType& getNativeSocket ()
{
return m_multiSocket->next_layer <NativeSocketType> ();
return m_socket->next_layer <NativeSocketType> ();
}
MultiSocket& getHandshakeStream ()
{
return *m_multiSocket;
return *m_socket;
}
MultiSocket& getStream ()
{
return *m_multiSocket;
return *m_socket;
}
//---------------------------------------------------------------------------
@@ -82,21 +82,18 @@ public:
public:
PeerImp (boost::asio::io_service& io_service,
boost::asio::ssl::context& ctx,
boost::asio::ssl::context& ssl_context,
uint64 peerID,
bool inbound)
bool inbound,
MultiSocket::Flag flags)
: m_isInbound (inbound)
#if RIPPLE_PEER_USES_BEAST_MULTISOCKET
// We could optionally set Flag::client_role or Flag::server_role
// based on the inbound flag but MultiSocket can figure out out
// from the call to handshake.
//
, m_multiSocket (MultiSocket::New (
io_service, MultiSocket::Flag::ssl | MultiSocket::Flag::ssl_required))
, m_socket (MultiSocket::New (
io_service, ssl_context, flags.asBits ()))
, m_strand (io_service)
#else
, m_socket (io_service)
, m_ssl_stream (m_socket, ctx)
, m_ssl_stream (m_socket, ssl_context)
, m_strand (io_service)
#endif
, mHelloed (false)
@@ -2330,7 +2327,7 @@ void PeerImp::sendHello ()
h.set_nettime (getApp().getOPs ().getNetworkTimeNC ());
h.set_nodepublic (getApp().getLocalCredentials ().getNodePublic ().humanNodePublic ());
h.set_nodeproof (&vchSig[0], vchSig.size ());
h.set_ipv4port (getConfig ().PEER_PORT);
h.set_ipv4port (getConfig ().peerListeningPort);
h.set_nodeprivate (getConfig ().PEER_PRIVATE);
h.set_testnet (getConfig ().TESTNET);
@@ -2545,13 +2542,38 @@ Json::Value PeerImp::getJson ()
//------------------------------------------------------------------------------
Peer::pointer Peer::New (boost::asio::io_service& io_service,
boost::asio::ssl::context& ctx,
uint64 id,
bool inbound)
boost::asio::ssl::context& ssl_context, uint64 id,
bool inbound, bool requirePROXYHandshake)
{
return Peer::pointer (new PeerImp (io_service, ctx, id, inbound));
MultiSocket::Flag flags;
if (inbound)
{
flags = MultiSocket::Flag::server_role | MultiSocket::Flag::ssl_required;
if (requirePROXYHandshake)
{
#if RIPPLE_PEER_USES_BEAST_MULTISOCKET
flags = flags.with (MultiSocket::Flag::proxy);
#else
FatalError ("PROXY Handshake support disabled in this build",
__FILE__, __LINE__);
#endif
}
}
else
{
flags = MultiSocket::Flag::client_role | MultiSocket::Flag::ssl;
bassert (! requirePROXYHandshake);
}
return Peer::pointer (new PeerImp (
io_service, ssl_context, id, inbound, flags));
}
//------------------------------------------------------------------------------
void Peer::applyLoadCharge (boost::weak_ptr <Peer>& peerToPunish,
LoadType loadThatWasImposed)
{

View File

@@ -24,7 +24,8 @@ public:
static pointer New (boost::asio::io_service& io_service,
boost::asio::ssl::context& ctx,
uint64 id,
bool inbound);
bool inbound,
bool requirePROXYHandshake);
// VFALCO TODO see if this and below can be private
virtual void handleConnect (const boost::system::error_code& error,

View File

@@ -4,9 +4,11 @@
*/
//==============================================================================
class Peers
: public IPeers
, LeakChecked <Peers>
SETUP_LOG (Peers)
class PeersImp
: public Peers
, LeakChecked <PeersImp>
{
public:
enum
@@ -16,8 +18,10 @@ public:
policyIntervalSeconds = 5
};
explicit Peers (boost::asio::io_service& io_service)
: mPeerLock (this, "Peers", __FILE__, __LINE__)
PeersImp (boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
: m_io_service (io_service)
, m_ssl_context (ssl_context)
, mPeerLock (this, "PeersImp", __FILE__, __LINE__)
, mLastPeer (0)
, mPhase (0)
, mScanTimer (io_service)
@@ -84,16 +88,19 @@ public:
private:
typedef RippleRecursiveMutex LockType;
typedef LockType::ScopedLockType ScopedLockType;
typedef std::pair<RippleAddress, Peer::pointer> naPeer;
typedef std::pair<IPAndPortNumber, Peer::pointer> pipPeer;
typedef std::map<IPAndPortNumber, Peer::pointer>::value_type vtPeer;
boost::asio::io_service& m_io_service;
boost::asio::ssl::context& m_ssl_context;
LockType mPeerLock;
uint64 mLastPeer;
int mPhase;
typedef std::pair<RippleAddress, Peer::pointer> naPeer;
typedef std::pair<IPAndPortNumber, Peer::pointer> pipPeer;
typedef std::map<IPAndPortNumber, Peer::pointer>::value_type vtPeer;
// Peers we are connecting with and non-thin peers we are connected to.
// PeersImp we are connecting with and non-thin peers we are connected to.
// Only peers we know the connection ip for are listed.
// We know the ip and port for:
// - All outbound connections
@@ -101,7 +108,7 @@ private:
boost::unordered_map<IPAndPortNumber, Peer::pointer> mIpMap;
// Non-thin peers which we are connected to.
// Peers we have the public key for.
// PeersImp we have the public key for.
typedef boost::unordered_map<RippleAddress, Peer::pointer>::value_type vtConMap;
boost::unordered_map<RippleAddress, Peer::pointer> mConnectedMap;
@@ -119,7 +126,7 @@ private:
void policyHandler (const boost::system::error_code& ecResult);
// Peers we are establishing a connection with as a client.
// PeersImp we are establishing a connection with as a client.
// int miConnectStarting;
bool peerAvailable (std::string& strIp, int& iPort);
@@ -137,7 +144,7 @@ void splitIpPort (const std::string& strIpPort, std::string& strIp, int& iPort)
iPort = lexicalCastThrow <int> (vIpPort[1]);
}
void Peers::start ()
void PeersImp::start ()
{
if (getConfig ().RUN_STANDALONE)
return;
@@ -149,7 +156,7 @@ void Peers::start ()
scanRefresh ();
}
bool Peers::getTopNAddrs (int n, std::vector<std::string>& addrs)
bool PeersImp::getTopNAddrs (int n, std::vector<std::string>& addrs)
{
// Try current connections first
@@ -185,7 +192,7 @@ bool Peers::getTopNAddrs (int n, std::vector<std::string>& addrs)
return true;
}
bool Peers::savePeer (const std::string& strIp, int iPort, char code)
bool PeersImp::savePeer (const std::string& strIp, int iPort, char code)
{
bool bNew = false;
@@ -225,7 +232,7 @@ bool Peers::savePeer (const std::string& strIp, int iPort, char code)
return bNew;
}
Peer::pointer Peers::getPeerById (const uint64& id)
Peer::pointer PeersImp::getPeerById (const uint64& id)
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
const boost::unordered_map<uint64, Peer::pointer>::iterator& it = mPeerIdMap.find (id);
@@ -236,7 +243,7 @@ Peer::pointer Peers::getPeerById (const uint64& id)
return it->second;
}
bool Peers::hasPeer (const uint64& id)
bool PeersImp::hasPeer (const uint64& id)
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
return mPeerIdMap.find (id) != mPeerIdMap.end ();
@@ -246,7 +253,7 @@ bool Peers::hasPeer (const uint64& id)
// too.
//
// <-- true, if a peer is available to connect to
bool Peers::peerAvailable (std::string& strIp, int& iPort)
bool PeersImp::peerAvailable (std::string& strIp, int& iPort)
{
Database* db = getApp().getWalletDB ()->getDB ();
std::vector<std::string> vstrIpPort;
@@ -290,7 +297,7 @@ bool Peers::peerAvailable (std::string& strIp, int& iPort)
}
// Make sure we have at least low water connections.
void Peers::policyLowWater ()
void PeersImp::policyLowWater ()
{
std::string strIp;
int iPort;
@@ -335,7 +342,7 @@ void Peers::policyLowWater ()
}
}
void Peers::policyEnforce ()
void PeersImp::policyEnforce ()
{
// Cancel any in progress timer.
(void) mPolicyTimer.cancel ();
@@ -351,10 +358,10 @@ void Peers::policyEnforce ()
// Schedule next enforcement.
mPolicyTimer.expires_at (boost::posix_time::second_clock::universal_time () + boost::posix_time::seconds (policyIntervalSeconds));
mPolicyTimer.async_wait (BIND_TYPE (&Peers::policyHandler, this, P_1));
mPolicyTimer.async_wait (BIND_TYPE (&PeersImp::policyHandler, this, P_1));
}
void Peers::policyHandler (const boost::system::error_code& ecResult)
void PeersImp::policyHandler (const boost::system::error_code& ecResult)
{
if (ecResult == boost::asio::error::operation_aborted)
{
@@ -372,7 +379,7 @@ void Peers::policyHandler (const boost::system::error_code& ecResult)
// YYY: Should probably do this in the background.
// YYY: Might end up sending to disconnected peer?
int Peers::relayMessage (Peer* fromPeer, const PackedMessage::pointer& msg)
int PeersImp::relayMessage (Peer* fromPeer, const PackedMessage::pointer& msg)
{
int sentTo = 0;
std::vector<Peer::pointer> peerVector = getPeerVector ();
@@ -388,7 +395,7 @@ int Peers::relayMessage (Peer* fromPeer, const PackedMessage::pointer& msg)
return sentTo;
}
int Peers::relayMessageCluster (Peer* fromPeer, const PackedMessage::pointer& msg)
int PeersImp::relayMessageCluster (Peer* fromPeer, const PackedMessage::pointer& msg)
{
int sentTo = 0;
std::vector<Peer::pointer> peerVector = getPeerVector ();
@@ -404,7 +411,7 @@ int Peers::relayMessageCluster (Peer* fromPeer, const PackedMessage::pointer& ms
return sentTo;
}
void Peers::relayMessageBut (const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
void PeersImp::relayMessageBut (const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
{
// Relay message to all but the specified peers
std::vector<Peer::pointer> peerVector = getPeerVector ();
@@ -416,7 +423,7 @@ void Peers::relayMessageBut (const std::set<uint64>& fromPeers, const PackedMess
}
void Peers::relayMessageTo (const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
void PeersImp::relayMessageTo (const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
{
// Relay message to the specified peers
std::vector<Peer::pointer> peerVector = getPeerVector ();
@@ -432,7 +439,7 @@ void Peers::relayMessageTo (const std::set<uint64>& fromPeers, const PackedMessa
//
// Add or modify into PeerIps as a manual entry for immediate scanning.
// Requires sane IP and port.
void Peers::connectTo (const std::string& strIp, int iPort)
void PeersImp::connectTo (const std::string& strIp, int iPort)
{
{
Database* db = getApp().getWalletDB ()->getDB ();
@@ -450,24 +457,23 @@ void Peers::connectTo (const std::string& strIp, int iPort)
// Start a connection, if not already known connected or connecting.
//
// <-- true, if already connected.
Peer::pointer Peers::peerConnect (const std::string& strIp, int iPort)
Peer::pointer PeersImp::peerConnect (const std::string& strIp, int iPort)
{
IPAndPortNumber pipPeer = make_pair (strIp, iPort);
Peer::pointer ppResult;
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
if (mIpMap.find (pipPeer) == mIpMap.end ())
{
ppResult = Peer::New (getApp().getIOService (),
getApp().getPeerDoor ().getSSLContext (),
++mLastPeer,
false);
bool const isInbound (false);
bool const requirePROXYHandshake (false);
mIpMap[pipPeer] = ppResult;
// ++miConnectStarting;
ppResult = Peer::New (m_io_service, m_ssl_context,
++mLastPeer, isInbound, requirePROXYHandshake);
mIpMap [pipPeer] = ppResult;
}
}
@@ -485,7 +491,7 @@ Peer::pointer Peers::peerConnect (const std::string& strIp, int iPort)
}
// Returns information on verified peers.
Json::Value Peers::getPeersJson ()
Json::Value PeersImp::getPeersJson ()
{
Json::Value ret (Json::arrayValue);
std::vector<Peer::pointer> vppPeers = getPeerVector ();
@@ -498,14 +504,14 @@ Json::Value Peers::getPeersJson ()
return ret;
}
int Peers::getPeerCount ()
int PeersImp::getPeerCount ()
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
return mConnectedMap.size ();
}
std::vector<Peer::pointer> Peers::getPeerVector ()
std::vector<Peer::pointer> PeersImp::getPeerVector ()
{
std::vector<Peer::pointer> ret;
@@ -522,7 +528,7 @@ std::vector<Peer::pointer> Peers::getPeerVector ()
return ret;
}
uint64 Peers::assignPeerId ()
uint64 PeersImp::assignPeerId ()
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
return ++mLastPeer;
@@ -530,7 +536,7 @@ uint64 Peers::assignPeerId ()
// Now know peer's node public key. Determine if we want to stay connected.
// <-- bNew: false = redundant
bool Peers::peerConnected (Peer::ref peer, const RippleAddress& naPeer,
bool PeersImp::peerConnected (Peer::ref peer, const RippleAddress& naPeer,
const std::string& strIP, int iPort)
{
bool bNew = false;
@@ -592,7 +598,7 @@ bool Peers::peerConnected (Peer::ref peer, const RippleAddress& naPeer,
}
// We maintain a map of public key to peer for connected and verified peers. Maintain it.
void Peers::peerDisconnected (Peer::ref peer, const RippleAddress& naPeer)
void PeersImp::peerDisconnected (Peer::ref peer, const RippleAddress& naPeer)
{
ScopedLockType sl (mPeerLock, __FILE__, __LINE__);
@@ -632,7 +638,7 @@ void Peers::peerDisconnected (Peer::ref peer, const RippleAddress& naPeer)
// Schedule for immediate scanning, if not already scheduled.
//
// <-- true, scanRefresh needed.
bool Peers::peerScanSet (const std::string& strIp, int iPort)
bool PeersImp::peerScanSet (const std::string& strIp, int iPort)
{
std::string strIpPort = str (boost::format ("%s %d") % strIp % iPort);
bool bScanDirty = false;
@@ -682,7 +688,7 @@ bool Peers::peerScanSet (const std::string& strIp, int iPort)
}
// --> strIp: not empty
void Peers::peerClosed (Peer::ref peer, const std::string& strIp, int iPort)
void PeersImp::peerClosed (Peer::ref peer, const std::string& strIp, int iPort)
{
IPAndPortNumber ipPeer = make_pair (strIp, iPort);
bool bScanRefresh = false;
@@ -735,7 +741,7 @@ void Peers::peerClosed (Peer::ref peer, const std::string& strIp, int iPort)
scanRefresh ();
}
void Peers::peerVerified (Peer::ref peer)
void PeersImp::peerVerified (Peer::ref peer)
{
if (mScanning && mScanning == peer)
{
@@ -770,7 +776,7 @@ void Peers::peerVerified (Peer::ref peer)
}
}
void Peers::scanHandler (const boost::system::error_code& ecResult)
void PeersImp::scanHandler (const boost::system::error_code& ecResult)
{
if (ecResult == boost::asio::error::operation_aborted)
{
@@ -786,7 +792,7 @@ void Peers::scanHandler (const boost::system::error_code& ecResult)
}
}
void Peers::makeConfigured ()
void PeersImp::makeConfigured ()
{
if (getConfig ().RUN_STANDALONE)
return;
@@ -802,7 +808,7 @@ void Peers::makeConfigured ()
}
// Scan ips as per db entries.
void Peers::scanRefresh ()
void PeersImp::scanRefresh ()
{
if (getConfig ().RUN_STANDALONE)
{
@@ -894,27 +900,15 @@ void Peers::scanRefresh ()
// % strIpPort % tpNext % (tpNext-tpNow).total_seconds());
mScanTimer.expires_at (tpNext);
mScanTimer.async_wait (BIND_TYPE (&Peers::scanHandler, this, P_1));
mScanTimer.async_wait (BIND_TYPE (&PeersImp::scanHandler, this, P_1));
}
}
}
IPeers* IPeers::New (boost::asio::io_service& io_service)
//------------------------------------------------------------------------------
Peers* Peers::New (boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
{
return new Peers (io_service);
return new PeersImp (io_service, ssl_context);
}
#if 0
bool Peers::isMessageKnown (PackedMessage::pointer msg)
{
for (unsigned int n = 0; n < mBroadcastMessages.size (); n++)
{
if (msg == mBroadcastMessages[n].first) return (false);
}
return (false);
}
#endif
SETUP_LOG (Peers)

View File

@@ -4,17 +4,18 @@
*/
//==============================================================================
#ifndef RIPPLE_IPEERS_H_INCLUDED
#define RIPPLE_IPEERS_H_INCLUDED
#ifndef RIPPLE_PEERS_H_INCLUDED
#define RIPPLE_PEERS_H_INCLUDED
/** Manages the set of connected peers.
*/
class IPeers
class Peers
{
public:
static IPeers* New (boost::asio::io_service& io_service);
static Peers* New (boost::asio::io_service& io_service,
boost::asio::ssl::context& context);
virtual ~IPeers () { }
virtual ~Peers () { }
// Begin enforcing connection policy.
virtual void start () = 0;

View File

@@ -134,8 +134,8 @@ namespace ripple
#include "misc/ripple_IFeatures.h"
#include "misc/ripple_IFeeVote.h"
#include "misc/ripple_IHashRouter.h"
#include "peers/ripple_Peer.h" // VFALCO TODO Rename to IPeer
#include "peers/ripple_IPeers.h"
#include "peers/ripple_Peer.h"
#include "peers/ripple_Peers.h"
#include "misc/ripple_IProofOfWorkFactory.h"
#include "peers/ripple_ClusterNodeStatus.h"
#include "peers/ripple_UniqueNodeList.h"
@@ -156,7 +156,7 @@ namespace ripple
#include "misc/NetworkOPs.h"
#include "tx/TransactionMaster.h"
#include "main/ripple_LocalCredentials.h"
#include "network/WSDoor.h"
#include "websocket/WSDoor.h"
#include "boost/ripple_IoService.h"
#include "boost/ripple_SslContext.h"
#include "main/ripple_Application.h"
@@ -188,8 +188,8 @@ namespace ripple
#include "paths/ripple_RippleState.h"
#include "tx/AccountSetTransactor.h"
#include "tx/TrustSetTransactor.h"
#include "network/WSConnection.h"
#include "network/ripple_WSHandler.h"
#include "websocket/WSConnection.h"
#include "websocket/WSServerHandler.h"
#include "tx/WalletAddTransactor.h"
#include "contracts/ripple_ScriptData.h"
@@ -306,14 +306,6 @@ static const uint64 tenTo17m1 = tenTo17 - 1;
#if ! defined (RIPPLE_MAIN_PART) || RIPPLE_MAIN_PART == 3
// This is for PeerDoor and WSDoor
// Generate DH for SSL connection.
static DH* handleTmpDh (SSL* ssl, int is_export, int iKeyLength)
{
// VFALCO TODO eliminate this horrendous dependency on theApp and LocalCredentials
return 512 == iKeyLength ? getApp().getLocalCredentials ().getDh512 () : getApp().getLocalCredentials ().getDh1024 ();
}
#include "paths/ripple_RippleCalc.cpp"
#include "paths/ripple_PathState.cpp"
#include "rpc/CallRPC.cpp"
@@ -329,8 +321,8 @@ static DH* handleTmpDh (SSL* ssl, int is_export, int iKeyLength)
#include "tx/TransactionEngine.cpp"
#include "tx/TransactionMeta.cpp"
#include "tx/Transactor.cpp"
#include "network/WSConnection.cpp"
#include "network/WSDoor.cpp"
#include "websocket/WSConnection.cpp"
#include "websocket/WSDoor.cpp"
#endif
@@ -349,7 +341,7 @@ static DH* handleTmpDh (SSL* ssl, int is_export, int iKeyLength)
#include "tx/TransactionMaster.cpp"
#include "tx/TransactionQueue.cpp"
#include "tx/TrustSetTransactor.cpp"
#include "network/ripple_WSHandler.cpp"
#include "websocket/WSServerHandler.cpp"
#endif
@@ -369,6 +361,7 @@ namespace ripple
#include "tx/OfferCreateTransactor.cpp"
#include "misc/ripple_Validations.cpp"
#include "main/ripple_LocalCredentials.cpp"
#include "tx/WalletAddTransactor.cpp"
#include "ledger/ripple_AcceptedLedgerTx.cpp"
#include "misc/ripple_FeeVote.cpp"
@@ -384,7 +377,6 @@ namespace ripple
#include "paths/ripple_Pathfinder.cpp"
#include "misc/ripple_Features.cpp"
#include "main/ripple_LocalCredentials.cpp"
#include "ledger/ripple_AcceptedLedger.cpp"
#include "consensus/ripple_DisputedTx.cpp"
#include "misc/ripple_HashRouter.cpp"

View File

@@ -0,0 +1,134 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
SETUP_LOG (WSDoor)
//
// This is a light weight, untrusted interface for web clients.
// For now we don't provide proof. Later we will.
//
// Might need to support this header for browsers: Access-Control-Allow-Origin: *
// - https://developer.mozilla.org/en-US/docs/HTTP_access_control
//
//
// Strategy:
// - We only talk to NetworkOPs (so we will work even in thin mode)
// - NetworkOPs is smart enough to subscribe and or pass back messages
//
// VFALCO NOTE NetworkOPs isn't used here...
//
class WSDoorImp : public WSDoor, protected Thread, LeakChecked <WSDoorImp>
{
public:
WSDoorImp (std::string const& strIp, int iPort, bool bPublic,
boost::asio::ssl::context& ssl_context)
: Thread ("websocket")
, m_ssl_context (ssl_context)
, m_endpointLock (this, "WSDoor", __FILE__, __LINE__)
, mPublic (bPublic)
, mIp (strIp)
, mPort (iPort)
{
startThread ();
}
~WSDoorImp ()
{
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
if (m_endpoint != nullptr)
m_endpoint->stop ();
}
signalThreadShouldExit ();
waitForThreadToExit ();
}
private:
void run ()
{
WriteLog (lsINFO, WSDoor) << boost::str (
boost::format ("Websocket: %s: Listening: %s %d ") %
(mPublic ? "Public" : "Private") % mIp % mPort);
websocketpp::server_autotls::handler::ptr handler (
new WSServerHandler <websocketpp::server_autotls> (
m_ssl_context, mPublic));
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
m_endpoint = new websocketpp::server_autotls (handler);
}
// Call the main-event-loop of the websocket server.
try
{
m_endpoint->listen (
boost::asio::ip::tcp::endpoint (
boost::asio::ip::address ().from_string (mIp), mPort));
}
catch (websocketpp::exception& e)
{
WriteLog (lsWARNING, WSDoor) << "websocketpp exception: " << e.what ();
// temporary workaround for websocketpp throwing exceptions on access/close races
for (;;)
{
// https://github.com/zaphoyd/websocketpp/issues/98
try
{
m_endpoint->get_io_service ().run ();
break;
}
catch (websocketpp::exception& e)
{
WriteLog (lsWARNING, WSDoor) << "websocketpp exception: " << e.what ();
}
}
}
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
m_endpoint = nullptr;
}
}
private:
typedef RippleRecursiveMutex LockType;
typedef LockType::ScopedLockType ScopedLockType;
boost::asio::ssl::context& m_ssl_context;
LockType m_endpointLock;
ScopedPointer <websocketpp::server_autotls> m_endpoint;
bool mPublic;
std::string mIp;
int mPort;
};
//------------------------------------------------------------------------------
WSDoor* WSDoor::New (std::string const& strIp, int iPort, bool bPublic,
boost::asio::ssl::context& ssl_context)
{
ScopedPointer <WSDoor> door;
try
{
door = new WSDoorImp (strIp, iPort, bPublic, ssl_context);
}
catch (...)
{
door = nullptr;
}
return door.release ();
}

View File

@@ -0,0 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_WSDOOR_RIPPLEHEADER
#define RIPPLE_WSDOOR_RIPPLEHEADER
/** Handles accepting incoming WebSocket connections. */
class WSDoor
{
public:
static WSDoor* New (std::string const& strIp, int iPort, bool bPublic,
boost::asio::ssl::context& ssl_context);
};
#endif

View File

@@ -4,8 +4,8 @@
*/
//==============================================================================
#ifndef RIPPLE_WSHANDLER_H_INCLUDED
#define RIPPLE_WSHANDLER_H_INCLUDED
#ifndef RIPPLE_WSSERVERHANDLER_H_INCLUDED
#define RIPPLE_WSSERVERHANDLER_H_INCLUDED
extern bool serverOkay (std::string& reason);
@@ -47,39 +47,34 @@ protected:
LockType mLock;
private:
boost::shared_ptr<boost::asio::ssl::context> mCtx;
boost::asio::ssl::context& m_ssl_context;
protected:
// For each connection maintain an associated object to track subscriptions.
boost::unordered_map<connection_ptr, boost::shared_ptr< WSConnection<endpoint_type> > > mMap;
bool mPublic;
boost::unordered_map <connection_ptr,
boost::shared_ptr <WSConnection <endpoint_type> > > mMap;
bool mPublic;
public:
WSServerHandler (boost::shared_ptr<boost::asio::ssl::context> spCtx, bool bPublic)
: mLock (static_cast <WSServerHandlerBase*> (this), "WSServerHandler", __FILE__, __LINE__)
, mCtx (spCtx)
WSServerHandler (boost::asio::ssl::context& ssl_context, bool bPublic)
: m_ssl_context (ssl_context)
, mLock (static_cast <WSServerHandlerBase*> (this), "WSServerHandler", __FILE__, __LINE__)
, mPublic (bPublic)
{
if (getConfig ().WEBSOCKET_SECURE != 0)
{
basio::SslContext::initializeFromFile (
*mCtx,
getConfig ().WEBSOCKET_SSL_KEY,
getConfig ().WEBSOCKET_SSL_CERT,
getConfig ().WEBSOCKET_SSL_CHAIN);
}
}
bool getPublic ()
bool getPublic ()
{
return mPublic;
};
/*
boost::asio::ssl::context& getASIOContext ()
{
return *mCtx;
return *m_ssl_context;
}
*/
static void ssend (connection_ptr cpClient, message_ptr mpMessage)
{
@@ -320,9 +315,9 @@ public:
}
}
boost::shared_ptr<boost::asio::ssl::context> on_tls_init ()
boost::asio::ssl::context& get_ssl_context ()
{
return mCtx;
return m_ssl_context;
}
// Respond to http requests.

View File

@@ -36,11 +36,8 @@
namespace ripple
{
# include "sockets/ripple_RippleTlsContext.h"
# include "sockets/ripple_MultiSocket.h"
#include "sockets/ripple_MultiSocketType.h"
#include "sockets/ripple_RippleTlsContext.cpp"
#include "sockets/RippleSSLContext.cpp"
#include "sockets/ripple_MultiSocket.cpp"
}

View File

@@ -14,6 +14,7 @@ namespace ripple
using namespace beast;
#include "sockets/RippleSSLContext.h"
#include "sockets/ripple_MultiSocket.h"
}

View File

@@ -0,0 +1,274 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
class RippleSSLContextImp : public RippleSSLContext
{
private:
boost::asio::ssl::context m_context;
public:
RippleSSLContextImp ()
: RippleSSLContext (m_context)
, m_context (boost::asio::ssl::context::sslv23)
{
m_context.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 (
m_context.native_handle (),
tmp_dh_handler);
}
~RippleSSLContextImp ()
{
}
static DH* tmp_dh_handler (SSL*, int, int key_length)
{
return DHparams_dup (getDH (key_length));
}
//--------------------------------------------------------------------------
static std::string getRawDHParams (int keySize)
{
std::string params;
// Original code provided the 512-bit keySize parameters
// when 1024 bits were requested so we will do the same.
if (keySize == 1024)
keySize = 512;
switch (keySize)
{
case 512:
{
// These are the DH parameters that OpenCoin has chosen for Ripple
//
uint8 const raw [] = {
0x30, 0x46, 0x02, 0x41, 0x00, 0x98, 0x15, 0xd2, 0xd0, 0x08, 0x32, 0xda,
0xaa, 0xac, 0xc4, 0x71, 0xa3, 0x1b, 0x11, 0xf0, 0x6c, 0x62, 0xb2, 0x35,
0x8a, 0x10, 0x92, 0xc6, 0x0a, 0xa3, 0x84, 0x7e, 0xaf, 0x17, 0x29, 0x0b,
0x70, 0xef, 0x07, 0x4f, 0xfc, 0x9d, 0x6d, 0x87, 0x99, 0x19, 0x09, 0x5b,
0x6e, 0xdb, 0x57, 0x72, 0x4a, 0x7e, 0xcd, 0xaf, 0xbd, 0x3a, 0x97, 0x55,
0x51, 0x77, 0x5a, 0x34, 0x7c, 0xe8, 0xc5, 0x71, 0x63, 0x02, 0x01, 0x02
};
params.resize (sizeof (raw));
std::copy (raw, raw + sizeof (raw), params.begin ());
}
break;
};
return params;
}
//--------------------------------------------------------------------------
void initAnonymous (String const& cipherList)
{
int const result = SSL_CTX_set_cipher_list (
m_context.native_handle (),
cipherList.toStdString ().c_str ());
if (result != 1)
FatalError ("invalid cipher list", __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
void initAuthenticated (
std::string key_file, std::string cert_file, std::string chain_file)
{
SSL_CTX* const ssl = m_context.native_handle ();
bool cert_set = false;
if (! cert_file.empty ())
{
boost::system::error_code error;
m_context.use_certificate_file (
cert_file, boost::asio::ssl::context::pem, error);
if (error)
{
FatalError ("Problem with SSL certificate file.",
__FILE__, __LINE__);
}
cert_set = true;
}
if (! chain_file.empty ())
{
// VFALCO Replace fopen() with RAII
FILE* f = fopen (chain_file.c_str (), "r");
if (!f)
{
FatalError ("Problem opening SSL chain file.",
__FILE__, __LINE__);
}
try
{
for (;;)
{
X509* const x = PEM_read_X509 (f, NULL, NULL, NULL);
if (x == nullptr)
break;
if (! cert_set)
{
if (SSL_CTX_use_certificate (ssl, x) != 1)
FatalError ("Problem retrieving SSL certificate from chain file.",
__FILE__, __LINE__);
cert_set = true;
}
else if (SSL_CTX_add_extra_chain_cert (ssl, x) != 1)
{
X509_free (x);
FatalError ("Problem adding SSL chain certificate.",
__FILE__, __LINE__);
}
}
fclose (f);
}
catch (...)
{
fclose (f);
FatalError ("Reading the SSL chain file generated an exception.",
__FILE__, __LINE__);
}
}
if (! key_file.empty ())
{
boost::system::error_code error;
m_context.use_private_key_file (key_file,
boost::asio::ssl::context::pem, error);
if (error)
{
FatalError ("Problem using the SSL private key file.",
__FILE__, __LINE__);
}
}
if (SSL_CTX_check_private_key (ssl) != 1)
{
FatalError ("Invalid key in SSL private key file.",
__FILE__, __LINE__);
}
}
//--------------------------------------------------------------------------
// A simple RAII container for a DH
//
struct ScopedDHPointer
{
// Construct from an existing DH
//
explicit ScopedDHPointer (DH* dh)
: m_dh (dh)
{
}
// Construct from raw DH params
//
explicit ScopedDHPointer (std::string const& params)
{
uint8 const* p (reinterpret_cast <uint8 const*>(&params [0]));
m_dh = d2i_DHparams (nullptr, &p, params.size ());
if (m_dh == nullptr)
FatalError ("d2i_DHparams returned nullptr.",
__FILE__, __LINE__);
}
~ScopedDHPointer ()
{
if (m_dh != nullptr)
DH_free (m_dh);
}
operator DH* () const
{
return get ();
}
DH* get () const
{
return m_dh;
}
private:
DH* m_dh;
};
//--------------------------------------------------------------------------
static DH* getDH (int keyLength)
{
if (keyLength == 512 || keyLength == 1024)
{
static ScopedDHPointer dh512 (getRawDHParams (keyLength));
return dh512.get ();
}
else
{
FatalError ("unsupported key length", __FILE__, __LINE__);
}
return nullptr;
}
};
//------------------------------------------------------------------------------
RippleSSLContext::RippleSSLContext (ContextType& context)
: SSLContext (context)
{
}
RippleSSLContext* RippleSSLContext::createBare ()
{
ScopedPointer <RippleSSLContextImp> context (new RippleSSLContextImp ());
return context.release ();
}
RippleSSLContext* RippleSSLContext::createAnonymous (String const& cipherList)
{
ScopedPointer <RippleSSLContextImp> context (new RippleSSLContextImp ());
context->initAnonymous (cipherList);
return context.release ();
}
RippleSSLContext* RippleSSLContext::createAuthenticated (
std::string key_file, std::string cert_file, std::string chain_file)
{
ScopedPointer <RippleSSLContextImp> context (new RippleSSLContextImp ());
context->initAuthenticated (key_file, cert_file, chain_file);
return context.release ();
}
std::string RippleSSLContext::getRawDHParams (int keySize)
{
return RippleSSLContextImp::getRawDHParams (keySize);
}

View File

@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_ASIO_RIPPLESSLCONTEXT_H_INCLUDED
#define RIPPLE_ASIO_RIPPLESSLCONTEXT_H_INCLUDED
/** The SSL contexts used by Ripple.
This is what Ripple uses for its secure connections. The ECDSA curve
parameters are predefined and verified to be secure. The context is set to
sslv23, Transport Layer Security / General. This is primarily used for peer to peer servers that don't care
about certificates or identity verification.
*/
class RippleSSLContext : public SSLContext
{
public:
/** Retrieve raw DH parameters.
This is in the format expected by the OpenSSL function d2i_DHparams.
The vector is binary. An empty vector means the key size is unsupported.
@note The string may contain nulls in the middle. Use size() to
determine the actual size.
*/
static std::string getRawDHParams (int keySize);
/** Creates a bare context.
This is for WebSocket connections that don't use certificates.
*/
static RippleSSLContext* createBare ();
/** Create a context that allows anonymous connections.
No certificates are required. Peers use this context.
If the cipher list is invalid, a fatal error is raised.
*/
static RippleSSLContext* createAnonymous (String const& cipherList);
/** Create a context with authentication requirements.
This is used for WebSocket connections.
The authentication credentials are loaded from the files with
the specified names. If an error occurs, a fatal error is raised.
*/
static RippleSSLContext* createAuthenticated (
std::string key_file, std::string cert_file, std::string chain_file);
protected:
explicit RippleSSLContext (ContextType& context);
};
#endif

View File

@@ -4,50 +4,13 @@
*/
//==============================================================================
MultiSocket* MultiSocket::New (boost::asio::io_service& io_service, int flags)
{
return new MultiSocketType <boost::asio::ip::tcp::socket> (io_service, flags);
}
MultiSocket* MultiSocket::New (boost::asio::ip::tcp::socket& socket, int flags)
{
return new MultiSocketType <boost::asio::ip::tcp::socket&> (socket, flags);
}
MultiSocket* MultiSocket::New (
boost::asio::ssl::stream <
boost::asio::ip::tcp::socket&>& stream, int flags)
boost::asio::io_service& io_service,
boost::asio::ssl::context& ssl_context,
int flags)
{
return new MultiSocketType <
boost::asio::ssl::stream <
boost::asio::ip::tcp::socket&>& > (stream, flags);
}
struct RippleTlsContextHolder
{
RippleTlsContextHolder ()
: m_context (RippleTlsContext::New ())
{
}
RippleTlsContext& get ()
{
return *m_context;
}
private:
ScopedPointer <RippleTlsContext> m_context;
};
static RippleTlsContextHolder s_context_holder;
SslContextBase::BoostContextType &MultiSocket::getRippleTlsBoostContext ()
{
// This doesn't work because VS2012 doesn't wrap
// it with a thread-safety preamble!!
//static ScopedPointer <RippleTlsContext> context (RippleTlsContext::New ());
return s_context_holder.get ().getBoostContext ();
return new MultiSocketType <boost::asio::ip::tcp::socket> (
io_service, ssl_context, flags);
}
//------------------------------------------------------------------------------
@@ -92,6 +55,27 @@ public:
return s;
}
static boost::asio::ssl::context& getSSLContext ()
{
struct ContextHolder
{
ContextHolder ()
: context (RippleSSLContext::createAnonymous (
"ALL:!LOW:!EXP:!MD5:@STRENGTH"))
{
// VFALCO NOTE Not sure if this is needed?
context->get().set_verify_mode (
boost::asio::ssl::verify_none);
}
ScopedPointer <RippleSSLContext> context;
};
static ContextHolder holder;
return holder.context->get ();
}
String name ()
{
return getArgName (m_flags);
@@ -122,11 +106,11 @@ public:
typedef socket_type native_socket_type;
typedef acceptor_type native_acceptor_type;
explicit MultiSocketDetailsType (arg_type flags)
MultiSocketDetailsType (arg_type flags)
: MultiSocketDetails (flags)
, m_socket (get_io_service ())
, m_acceptor (get_io_service ())
, m_multiSocket (m_socket, flags)
, m_multiSocket (m_socket, MultiSocketDetails::getSSLContext (), flags)
, m_acceptor_wrapper (m_acceptor)
{
}

View File

@@ -31,11 +31,17 @@ public:
// server: will require ssl (ignores ssl flag)
};
Flag (int flags) noexcept
Flag (int flags = 0) noexcept
: m_flags (flags)
{
}
Flag& operator= (int mask) noexcept
{
m_flags = mask;
return *this;
}
bool operator== (Flag const& other) const noexcept
{
return m_flags == other.m_flags;
@@ -61,6 +67,11 @@ public:
return Flag (m_flags & ~mask);
}
int asBits () const noexcept
{
return m_flags;
}
private:
int m_flags;
};
@@ -76,22 +87,10 @@ public:
virtual SSL* native_handle () = 0;
/*
// This would be the underlying StreamSocket template parameter
typedef boost::asio::ip::tcp::socket NativeSocketType;
typedef boost::asio::ssl::stream <NativeSocketType&> SslStreamType;
virtual boost::asio::ip::tcp::socket& getNativeSocket () = 0;
virtual SslStreamType& getSslStream () = 0;
*/
static MultiSocket* New (boost::asio::io_service& io_service, int flags = 0);
static MultiSocket* New (boost::asio::ip::tcp::socket& socket, int flags = 0);
static MultiSocket* New (boost::asio::ssl::stream <boost::asio::ip::tcp::socket&>& stream, int flags = 0);
// Ripple uses a SSL/TLS context with specific parameters and this returns
// a reference to the corresponding boost::asio::ssl::context object.
//
static SslContextBase::BoostContextType& getRippleTlsBoostContext ();
static MultiSocket* New (
boost::asio::io_service& io_service,
boost::asio::ssl::context& ssl_context,
int flags = 0);
};
#endif

View File

@@ -4,8 +4,8 @@
*/
//==============================================================================
#ifndef RIPPLE_MULTISOCKETTYPE_H_INCLUDED
#define RIPPLE_MULTISOCKETTYPE_H_INCLUDED
#ifndef RIPPLE_ASIO_MULTISOCKETTYPE_H_INCLUDED
#define RIPPLE_ASIO_MULTISOCKETTYPE_H_INCLUDED
/** Template for producing instances of MultiSocket
*/
@@ -21,10 +21,11 @@ public:
typedef typename boost::add_reference <next_layer_type>::type next_layer_type_ref;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
template <class Arg>
explicit MultiSocketType (Arg& arg, int flags = 0)
template <typename Arg>
MultiSocketType (Arg& arg, boost::asio::ssl::context& ssl_context, int flags)
: m_flags (flags)
, m_state (stateNone)
, m_ssl_context (ssl_context)
, m_verify_mode (0)
, m_stream (nullptr)
, m_needsShutdown (false)
@@ -75,28 +76,6 @@ protected:
return *m_stream;
}
#if 0
next_layer_type& next_layer () noexcept
{
return m_next_layer;
}
next_layer_type const& next_layer () const noexcept
{
return m_next_layer;
}
lowest_layer_type& lowest_layer () noexcept
{
return m_next_layer.lowest_layer ();
}
lowest_layer_type const& lowest_layer () const noexcept
{
return m_next_layer.lowest_layer ();
}
#endif
//--------------------------------------------------------------------------
//
// Socket
@@ -609,8 +588,7 @@ protected:
{
typedef typename boost::asio::ssl::stream <next_layer_type&> SslStream;
typedef SocketWrapperStrand <SslStream> Wrapper;
Wrapper* const socket = new Wrapper (
m_next_layer, MultiSocket::getRippleTlsBoostContext ());
Wrapper* const socket = new Wrapper (m_next_layer, m_ssl_context);
set_ssl_stream (socket->this_layer ());
return socket;
}
@@ -626,8 +604,7 @@ protected:
typedef boost::asio::ssl::stream <
PrefilledReadStream <next_layer_type&> > SslStream;
typedef SocketWrapperStrand <SslStream> Wrapper;
Wrapper* const socket = new Wrapper (
m_next_layer, MultiSocket::getRippleTlsBoostContext ());
Wrapper* const socket = new Wrapper (m_next_layer, m_ssl_context);
socket->this_layer ().next_layer().fill (buffers);
set_ssl_stream (socket->this_layer ());
return socket;
@@ -953,13 +930,12 @@ protected:
private:
Flag m_flags;
State m_state;
boost::asio::ssl::context& m_ssl_context;
int m_verify_mode;
ScopedPointer <Socket> m_stream;
ScopedPointer <Socket> m_ssl_stream; // the ssl portion of our stream if it exists
bool m_needsShutdown;
StreamSocket m_next_layer;
SSL* m_native_ssl_handle;
};

View File

@@ -1,151 +0,0 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
//------------------------------------------------------------------------------
class RippleTlsContextImp : public RippleTlsContext
{
public:
RippleTlsContextImp ()
: m_context (boost::asio::ssl::context::sslv23)
{
initBoostContext (m_context);
}
~RippleTlsContextImp ()
{
}
BoostContextType& getBoostContext () noexcept
{
return m_context;
}
//--------------------------------------------------------------------------
private:
boost::asio::ssl::context m_context;
};
//------------------------------------------------------------------------------
void RippleTlsContext::initBoostContext (BoostContextType& context)
{
struct Helpers
{
typedef boost::array <unsigned char, 72> RawDHParams;
// A simple RAII container for a DH
struct ScopedDHPointer
{
explicit ScopedDHPointer (DH* dh)
: m_dh (dh)
{
}
~ScopedDHPointer ()
{
if (m_dh != nullptr)
DH_free (m_dh);
}
operator DH* () const
{
return get ();
}
DH* get () const
{
return m_dh;
}
private:
unsigned char const* m_p;
DH* m_dh;
};
//----------------------------------------------------------------------
// These are the DH parameters that OpenCoin has chosen for Ripple
//
static RawDHParams const& getRaw512Params () noexcept
{
static RawDHParams params =
{ {
0x30, 0x46, 0x02, 0x41, 0x00, 0x98, 0x15, 0xd2, 0xd0, 0x08, 0x32, 0xda,
0xaa, 0xac, 0xc4, 0x71, 0xa3, 0x1b, 0x11, 0xf0, 0x6c, 0x62, 0xb2, 0x35,
0x8a, 0x10, 0x92, 0xc6, 0x0a, 0xa3, 0x84, 0x7e, 0xaf, 0x17, 0x29, 0x0b,
0x70, 0xef, 0x07, 0x4f, 0xfc, 0x9d, 0x6d, 0x87, 0x99, 0x19, 0x09, 0x5b,
0x6e, 0xdb, 0x57, 0x72, 0x4a, 0x7e, 0xcd, 0xaf, 0xbd, 0x3a, 0x97, 0x55,
0x51, 0x77, 0x5a, 0x34, 0x7c, 0xe8, 0xc5, 0x71, 0x63, 0x02, 0x01, 0x02
} };
return params;
}
static DH* createDH (RawDHParams const& rawParams)
{
RawDHParams::const_iterator iter = rawParams.begin ();
return d2i_DHparams (nullptr, &iter, rawParams.size ());
}
//----------------------------------------------------------------------
static DH* getDhParameters (int keyLength)
{
if (keyLength == 512 || keyLength == 1024)
{
static ScopedDHPointer dh512 (createDH (getRaw512Params ()));
return dh512.get ();
}
else
{
FatalError ("unsupported key length", __FILE__, __LINE__);
}
return nullptr;
}
static DH* tmp_dh_handler (SSL*, int, int key_length)
{
return DHparams_dup (getDhParameters (key_length));
}
static char const* getCipherList ()
{
static char const* ciphers = "ALL:!LOW:!EXP:!MD5:@STRENGTH";
return ciphers;
}
};
//--------------------------------------------------------------------------
context.set_options (
boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::single_dh_use);
context.set_verify_mode (boost::asio::ssl::verify_none);
SSL_CTX_set_tmp_dh_callback (
context.native_handle (),
Helpers::tmp_dh_handler);
int const result = SSL_CTX_set_cipher_list (
context.native_handle (),
Helpers::getCipherList ());
if (result != 1)
FatalError ("invalid cipher list", __FILE__, __LINE__);
}
//------------------------------------------------------------------------------
RippleTlsContext* RippleTlsContext::New ()
{
return new RippleTlsContextImp ();
}

View File

@@ -1,32 +0,0 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_RIPPLETLSCONTEXT_H_INCLUDED
#define RIPPLE_RIPPLETLSCONTEXT_H_INCLUDED
/** A boost SSL context which is set to Generic SSL/TLS (sslv23).
This is what Ripple uses for its secure connections. The
curve parameters are predefined and verified to be secure.
The context is set to sslv23, Transport Layer Security / General.
This is primarily used for peer to peer servers that don't care
about certificates or identity verification.
Usually you don't instantiate this directly, you will need to derive
a class and initialize the context in your constructor.
@see SslContext
*/
class RippleTlsContext : public SslContextBase
{
public:
static RippleTlsContext* New ();
static void initBoostContext (BoostContextType& context);
};
#endif

View File

@@ -35,7 +35,6 @@ Config::Config ()
TESTNET = false;
NETWORK_START_TIME = 1319844908;
PEER_PORT = SYSTEM_PEER_PORT;
RPC_SECURE = 0;
WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT;
WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT;
@@ -90,7 +89,9 @@ Config::Config ()
// VFALCO NOTE Clean area
//
proxyListeningPort = 0;
peerListeningPort = SYSTEM_PEER_PORT;
peerPROXYListeningPort = 0;
//
//
@@ -309,9 +310,6 @@ void Config::load ()
(void) SectionSingleB (secConfig, SECTION_PEER_IP, PEER_IP);
if (SectionSingleB (secConfig, SECTION_PEER_PORT, strTemp))
PEER_PORT = lexicalCastThrow <int> (strTemp);
if (SectionSingleB (secConfig, SECTION_PEER_PRIVATE, strTemp))
PEER_PRIVATE = lexicalCastThrow <bool> (strTemp);
@@ -341,10 +339,21 @@ void Config::load ()
importNodeDatabase = parseKeyValueSection (
secConfig, ConfigSection::importNodeDatabase ());
if (SectionSingleB (secConfig, SECTION_PEER_PROXY_PORT, strTemp)
proxyListeningPort = lexicalCastThrow <int> (strTemp);
if (SectionSingleB (secConfig, SECTION_PEER_PORT, strTemp))
peerListeningPort = lexicalCastThrow <int> (strTemp);
if (SectionSingleB (secConfig, SECTION_PEER_PROXY_PORT, strTemp))
{
peerPROXYListeningPort = lexicalCastThrow <int> (strTemp);
if (peerPROXYListeningPort != 0 && peerPROXYListeningPort == peerListeningPort)
FatalError ("Peer and proxy listening ports can't be the same.",
__FILE__, __LINE__);
}
else
proxyListeningPort = 0;
{
peerPROXYListeningPort = 0;
}
//
// VFALCO END CLEAN

View File

@@ -85,6 +85,8 @@ public:
boost::filesystem::path DEBUG_LOGFILE;
boost::filesystem::path VALIDATORS_FILE; // As specifed in rippled.cfg.
//--------------------------------------------------------------------------
/** Parameters for the main NodeStore database.
This is 1 or more strings of the form <key>=<value>
@@ -119,6 +121,10 @@ public:
*/
StringPairArray importNodeDatabase;
// Listening port number for peer connections.
//
int peerListeningPort;
/** PROXY listening port number
If this is not zero, it indicates an additional port number on
which we should accept incoming Peer connections that will also
@@ -127,7 +133,9 @@ public:
The PROXY Protocol:
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
*/
int proxyListeningPort;
int peerPROXYListeningPort;
//--------------------------------------------------------------------------
bool ELB_SUPPORT; // Support Amazon ELB
@@ -180,7 +188,6 @@ public:
// Peer networking parameters
std::string PEER_IP;
int PEER_PORT;
int NUMBER_CONNECTIONS;
std::string PEER_SSL_CIPHER_LIST;
int PEER_SCAN_INTERVAL_MIN;