diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 2a31a53f5b..28efddc0bf 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -313,24 +313,6 @@
true
true
-
- true
- true
- true
- true
-
-
- true
- true
- true
- true
-
-
- true
- true
- true
- true
-
true
true
@@ -683,8 +665,26 @@
true
true
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
-
+
true
true
true
@@ -1421,9 +1421,6 @@
-
-
-
@@ -1441,7 +1438,7 @@
-
+
@@ -1475,11 +1472,14 @@
+
+
+
-
+
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index e1c8f21a15..149d4d28e8 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -124,9 +124,6 @@
{29393027-f1ed-4700-bbd1-c880091ab96b}
-
- {7c14e9df-6d8d-4ba3-b208-f89c1d0b6b30}
-
{66d2d40a-72bd-41f5-9cf9-1f464a40bb04}
@@ -160,6 +157,9 @@
{8476f6e8-7411-460f-bdef-68e3166078eb}
+
+ {7c14e9df-6d8d-4ba3-b208-f89c1d0b6b30}
+
@@ -714,15 +714,6 @@
[1] Ripple\ripple_app\misc
-
- [1] Ripple\ripple_app\network
-
-
- [1] Ripple\ripple_app\network
-
-
- [1] Ripple\ripple_app\network
-
[1] Ripple\ripple_app\paths
@@ -873,9 +864,6 @@
[1] Ripple\ripple_asio
-
- [1] Ripple\ripple_asio\sockets
-
[1] Ripple\ripple_app\boost
@@ -885,6 +873,18 @@
[0] Subtrees\beast
+
+ [1] Ripple\ripple_asio\sockets
+
+
+ [1] Ripple\ripple_app\websocket
+
+
+ [1] Ripple\ripple_app\websocket
+
+
+ [1] Ripple\ripple_app\websocket
+
@@ -1499,15 +1499,6 @@
[1] Ripple\ripple_app\misc
-
- [1] Ripple\ripple_app\network
-
-
- [1] Ripple\ripple_app\network
-
-
- [1] Ripple\ripple_app\network
-
[1] Ripple\ripple_app\paths
@@ -1529,9 +1520,6 @@
[1] Ripple\ripple_app\peers
-
- [1] Ripple\ripple_app\peers
-
[1] Ripple\ripple_app\peers
@@ -1658,9 +1646,6 @@
[1] Ripple\ripple_asio\sockets
-
- [1] Ripple\ripple_asio\sockets
-
[1] Ripple\ripple_asio\sockets
@@ -1676,6 +1661,21 @@
[1] Ripple\ripple_basics\utility
+
+ [1] Ripple\ripple_asio\sockets
+
+
+ [1] Ripple\ripple_app\websocket
+
+
+ [1] Ripple\ripple_app\websocket
+
+
+ [1] Ripple\ripple_app\websocket
+
+
+ [1] Ripple\ripple_app\peers
+
diff --git a/Subtrees/websocket/src/sockets/autotls.hpp b/Subtrees/websocket/src/sockets/autotls.hpp
index a3c57a9a5b..803e7e65b2 100644
--- a/Subtrees/websocket/src/sockets/autotls.hpp
+++ b/Subtrees/websocket/src/sockets/autotls.hpp
@@ -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 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 callback)
diff --git a/Subtrees/websocket/src/sockets/tls.hpp b/Subtrees/websocket/src/sockets/tls.hpp
index 34e7af8caa..d43be49e3b 100644
--- a/Subtrees/websocket/src/sockets/tls.hpp
+++ b/Subtrees/websocket/src/sockets/tls.hpp
@@ -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 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 callback)
diff --git a/modules/ripple_app/main/ripple_Application.cpp b/modules/ripple_app/main/ripple_Application.cpp
index 469420e42a..542fabc10c 100644
--- a/modules/ripple_app/main/ripple_Application.cpp
+++ b/modules/ripple_app/main/ripple_Application.cpp
@@ -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 m_peerSSLContext;
+ ScopedPointer m_wsSSLContext;
ScopedPointer m_nodeStore;
ScopedPointer m_validators;
ScopedPointer mFeatures;
@@ -675,8 +706,12 @@ private:
ScopedPointer mValidations;
ScopedPointer mUNL;
ScopedPointer mProofOfWorkFactory;
- ScopedPointer mPeers;
+ ScopedPointer m_peers;
ScopedPointer m_loadManager;
+ ScopedPointer m_peerDoor;
+ ScopedPointer m_peerProxyDoor;
+ ScopedPointer m_wsPublicDoor;
+ ScopedPointer m_wsPrivateDoor;
// VFALCO End Clean stuff
DatabaseCon* mRpcDB;
@@ -684,10 +719,7 @@ private:
DatabaseCon* mLedgerDB;
DatabaseCon* mWalletDB;
- ScopedPointer mPeerDoor;
ScopedPointer mRPCDoor;
- ScopedPointer mWSPublicDoor;
- ScopedPointer 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 ()
diff --git a/modules/ripple_app/main/ripple_Application.h b/modules/ripple_app/main/ripple_Application.h
index 1b60883b85..d705082122 100644
--- a/modules/ripple_app/main/ripple_Application.h
+++ b/modules/ripple_app/main/ripple_Application.h
@@ -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;
diff --git a/modules/ripple_app/main/ripple_LocalCredentials.cpp b/modules/ripple_app/main/ripple_LocalCredentials.cpp
index 297a982255..797d71a4f8 100644
--- a/modules/ripple_app/main/ripple_LocalCredentials.cpp
+++ b/modules/ripple_app/main/ripple_LocalCredentials.cpp
@@ -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 (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.
diff --git a/modules/ripple_app/main/ripple_LocalCredentials.h b/modules/ripple_app/main/ripple_LocalCredentials.h
index 86ebe9ac15..1eb04959fb 100644
--- a/modules/ripple_app/main/ripple_LocalCredentials.h
+++ b/modules/ripple_app/main/ripple_LocalCredentials.h
@@ -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
};
diff --git a/modules/ripple_app/network/WSDoor.cpp b/modules/ripple_app/network/WSDoor.cpp
deleted file mode 100644
index 4acb9c3c53..0000000000
--- a/modules/ripple_app/network/WSDoor.cpp
+++ /dev/null
@@ -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 mCtx;
- mCtx = boost::make_shared (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 (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 ();
-}
diff --git a/modules/ripple_app/network/WSDoor.h b/modules/ripple_app/network/WSDoor.h
deleted file mode 100644
index 135ad577ad..0000000000
--- a/modules/ripple_app/network/WSDoor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- Copyright (c) 2011-2013, OpenCoin, Inc.
-*/
-//==============================================================================
-
-#ifndef RIPPLE_WSDOOR_RIPPLEHEADER
-#define RIPPLE_WSDOOR_RIPPLEHEADER
-
-class WSDoor : protected Thread, LeakChecked
-{
-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 m_endpoint;
- bool mPublic;
- std::string mIp;
- int mPort;
-};
-
-#endif
-
-// vim:ts=4
diff --git a/modules/ripple_app/peers/PeerDoor.cpp b/modules/ripple_app/peers/PeerDoor.cpp
index 64bbe30bb2..c4f2905112 100644
--- a/modules/ripple_app/peers/PeerDoor.cpp
+++ b/modules/ripple_app/peers/PeerDoor.cpp
@@ -9,27 +9,14 @@ SETUP_LOG (PeerDoor)
class PeerDoorImp : public PeerDoor, LeakChecked
{
public:
- PeerDoorImp (std::string const& ip,
- int port,
- std::string const& sslCiphers,
- boost::asio::io_service& io_service)
- : mAcceptor (
- io_service,
- boost::asio::ip::tcp::endpoint (boost::asio::ip::address ().from_string (ip.empty () ? "0.0.0.0" : ip),
- port))
- , mCtx (boost::asio::ssl::context::sslv23)
+ 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);
}
diff --git a/modules/ripple_app/peers/PeerDoor.h b/modules/ripple_app/peers/PeerDoor.h
index decaa657ea..31fbcffa2c 100644
--- a/modules/ripple_app/peers/PeerDoor.h
+++ b/modules/ripple_app/peers/PeerDoor.h
@@ -14,13 +14,16 @@ class PeerDoor : LeakChecked
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
diff --git a/modules/ripple_app/peers/ripple_Peer.cpp b/modules/ripple_app/peers/ripple_Peer.cpp
index a93c51e827..051f00366f 100644
--- a/modules/ripple_app/peers/ripple_Peer.cpp
+++ b/modules/ripple_app/peers/ripple_Peer.cpp
@@ -33,22 +33,22 @@ public:
//
#if RIPPLE_PEER_USES_BEAST_MULTISOCKET
- ScopedPointer m_multiSocket;
+ ScopedPointer m_socket;
boost::asio::io_service& m_strand;
NativeSocketType& getNativeSocket ()
{
- return m_multiSocket->next_layer ();
+ return m_socket->next_layer ();
}
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 & peerToPunish,
LoadType loadThatWasImposed)
{
diff --git a/modules/ripple_app/peers/ripple_Peer.h b/modules/ripple_app/peers/ripple_Peer.h
index ba94073354..ee038435d4 100644
--- a/modules/ripple_app/peers/ripple_Peer.h
+++ b/modules/ripple_app/peers/ripple_Peer.h
@@ -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,
diff --git a/modules/ripple_app/peers/ripple_Peers.cpp b/modules/ripple_app/peers/ripple_Peers.cpp
index cec9a9169e..a629a7b0f1 100644
--- a/modules/ripple_app/peers/ripple_Peers.cpp
+++ b/modules/ripple_app/peers/ripple_Peers.cpp
@@ -4,9 +4,11 @@
*/
//==============================================================================
-class Peers
- : public IPeers
- , LeakChecked
+SETUP_LOG (Peers)
+
+class PeersImp
+ : public Peers
+ , LeakChecked
{
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 naPeer;
+ typedef std::pair pipPeer;
+ typedef std::map::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 naPeer;
- typedef std::pair pipPeer;
- typedef std::map::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 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::value_type vtConMap;
boost::unordered_map 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 (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& addrs)
+bool PeersImp::getTopNAddrs (int n, std::vector& addrs)
{
// Try current connections first
@@ -185,7 +192,7 @@ bool Peers::getTopNAddrs (int n, std::vector& 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::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 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 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 peerVector = getPeerVector ();
@@ -404,7 +411,7 @@ int Peers::relayMessageCluster (Peer* fromPeer, const PackedMessage::pointer& ms
return sentTo;
}
-void Peers::relayMessageBut (const std::set& fromPeers, const PackedMessage::pointer& msg)
+void PeersImp::relayMessageBut (const std::set& fromPeers, const PackedMessage::pointer& msg)
{
// Relay message to all but the specified peers
std::vector peerVector = getPeerVector ();
@@ -416,7 +423,7 @@ void Peers::relayMessageBut (const std::set& fromPeers, const PackedMess
}
-void Peers::relayMessageTo (const std::set& fromPeers, const PackedMessage::pointer& msg)
+void PeersImp::relayMessageTo (const std::set& fromPeers, const PackedMessage::pointer& msg)
{
// Relay message to the specified peers
std::vector peerVector = getPeerVector ();
@@ -432,7 +439,7 @@ void Peers::relayMessageTo (const std::set& 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 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 Peers::getPeerVector ()
+std::vector PeersImp::getPeerVector ()
{
std::vector ret;
@@ -522,7 +528,7 @@ std::vector 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)
-
diff --git a/modules/ripple_app/peers/ripple_IPeers.h b/modules/ripple_app/peers/ripple_Peers.h
similarity index 92%
rename from modules/ripple_app/peers/ripple_IPeers.h
rename to modules/ripple_app/peers/ripple_Peers.h
index bfa44ea4bc..91a88371f5 100644
--- a/modules/ripple_app/peers/ripple_IPeers.h
+++ b/modules/ripple_app/peers/ripple_Peers.h
@@ -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;
diff --git a/modules/ripple_app/ripple_app.cpp b/modules/ripple_app/ripple_app.cpp
index 626309ef13..91f585b9a4 100644
--- a/modules/ripple_app/ripple_app.cpp
+++ b/modules/ripple_app/ripple_app.cpp
@@ -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"
diff --git a/modules/ripple_app/network/WSConnection.cpp b/modules/ripple_app/websocket/WSConnection.cpp
similarity index 100%
rename from modules/ripple_app/network/WSConnection.cpp
rename to modules/ripple_app/websocket/WSConnection.cpp
diff --git a/modules/ripple_app/network/WSConnection.h b/modules/ripple_app/websocket/WSConnection.h
similarity index 100%
rename from modules/ripple_app/network/WSConnection.h
rename to modules/ripple_app/websocket/WSConnection.h
diff --git a/modules/ripple_app/websocket/WSDoor.cpp b/modules/ripple_app/websocket/WSDoor.cpp
new file mode 100644
index 0000000000..ba5e980ce1
--- /dev/null
+++ b/modules/ripple_app/websocket/WSDoor.cpp
@@ -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
+{
+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 (
+ 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 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 door;
+
+ try
+ {
+ door = new WSDoorImp (strIp, iPort, bPublic, ssl_context);
+ }
+ catch (...)
+ {
+ door = nullptr;
+ }
+
+ return door.release ();
+}
diff --git a/modules/ripple_app/websocket/WSDoor.h b/modules/ripple_app/websocket/WSDoor.h
new file mode 100644
index 0000000000..36aeb9002b
--- /dev/null
+++ b/modules/ripple_app/websocket/WSDoor.h
@@ -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
diff --git a/modules/ripple_app/network/ripple_WSHandler.cpp b/modules/ripple_app/websocket/WSServerHandler.cpp
similarity index 100%
rename from modules/ripple_app/network/ripple_WSHandler.cpp
rename to modules/ripple_app/websocket/WSServerHandler.cpp
diff --git a/modules/ripple_app/network/ripple_WSHandler.h b/modules/ripple_app/websocket/WSServerHandler.h
similarity index 91%
rename from modules/ripple_app/network/ripple_WSHandler.h
rename to modules/ripple_app/websocket/WSServerHandler.h
index 56a1f1b7c7..e155290bcf 100644
--- a/modules/ripple_app/network/ripple_WSHandler.h
+++ b/modules/ripple_app/websocket/WSServerHandler.h
@@ -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 mCtx;
+ boost::asio::ssl::context& m_ssl_context;
protected:
// For each connection maintain an associated object to track subscriptions.
- boost::unordered_map > > mMap;
- bool mPublic;
+ boost::unordered_map > > mMap;
+ bool mPublic;
public:
- WSServerHandler (boost::shared_ptr spCtx, bool bPublic)
- : mLock (static_cast (this), "WSServerHandler", __FILE__, __LINE__)
- , mCtx (spCtx)
+ WSServerHandler (boost::asio::ssl::context& ssl_context, bool bPublic)
+ : m_ssl_context (ssl_context)
+ , mLock (static_cast (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 on_tls_init ()
+ boost::asio::ssl::context& get_ssl_context ()
{
- return mCtx;
+ return m_ssl_context;
}
// Respond to http requests.
diff --git a/modules/ripple_asio/ripple_asio.cpp b/modules/ripple_asio/ripple_asio.cpp
index 4be730a092..61012c686e 100644
--- a/modules/ripple_asio/ripple_asio.cpp
+++ b/modules/ripple_asio/ripple_asio.cpp
@@ -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"
}
diff --git a/modules/ripple_asio/ripple_asio.h b/modules/ripple_asio/ripple_asio.h
index 93f9be5f05..eb9de42682 100644
--- a/modules/ripple_asio/ripple_asio.h
+++ b/modules/ripple_asio/ripple_asio.h
@@ -14,6 +14,7 @@ namespace ripple
using namespace beast;
+#include "sockets/RippleSSLContext.h"
#include "sockets/ripple_MultiSocket.h"
}
diff --git a/modules/ripple_asio/sockets/RippleSSLContext.cpp b/modules/ripple_asio/sockets/RippleSSLContext.cpp
new file mode 100644
index 0000000000..0ef7159c3f
--- /dev/null
+++ b/modules/ripple_asio/sockets/RippleSSLContext.cpp
@@ -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 (¶ms [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 context (new RippleSSLContextImp ());
+
+ return context.release ();
+}
+
+RippleSSLContext* RippleSSLContext::createAnonymous (String const& cipherList)
+{
+ ScopedPointer 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 context (new RippleSSLContextImp ());
+
+ context->initAuthenticated (key_file, cert_file, chain_file);
+
+ return context.release ();
+}
+
+std::string RippleSSLContext::getRawDHParams (int keySize)
+{
+ return RippleSSLContextImp::getRawDHParams (keySize);
+}
+
diff --git a/modules/ripple_asio/sockets/RippleSSLContext.h b/modules/ripple_asio/sockets/RippleSSLContext.h
new file mode 100644
index 0000000000..6310450b47
--- /dev/null
+++ b/modules/ripple_asio/sockets/RippleSSLContext.h
@@ -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
diff --git a/modules/ripple_asio/sockets/ripple_MultiSocket.cpp b/modules/ripple_asio/sockets/ripple_MultiSocket.cpp
index f65fe6eb43..dadfbda7d7 100644
--- a/modules/ripple_asio/sockets/ripple_MultiSocket.cpp
+++ b/modules/ripple_asio/sockets/ripple_MultiSocket.cpp
@@ -4,50 +4,13 @@
*/
//==============================================================================
-MultiSocket* MultiSocket::New (boost::asio::io_service& io_service, int flags)
-{
- return new MultiSocketType (io_service, flags);
-}
-
-MultiSocket* MultiSocket::New (boost::asio::ip::tcp::socket& socket, int flags)
-{
- return new MultiSocketType (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 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 context (RippleTlsContext::New ());
-
- return s_context_holder.get ().getBoostContext ();
+ return new MultiSocketType (
+ 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 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)
{
}
diff --git a/modules/ripple_asio/sockets/ripple_MultiSocket.h b/modules/ripple_asio/sockets/ripple_MultiSocket.h
index 888b78f4ef..48a12019c5 100644
--- a/modules/ripple_asio/sockets/ripple_MultiSocket.h
+++ b/modules/ripple_asio/sockets/ripple_MultiSocket.h
@@ -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 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 & 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
diff --git a/modules/ripple_asio/sockets/ripple_MultiSocketType.h b/modules/ripple_asio/sockets/ripple_MultiSocketType.h
index bf2fb979f7..14d50ad7df 100644
--- a/modules/ripple_asio/sockets/ripple_MultiSocketType.h
+++ b/modules/ripple_asio/sockets/ripple_MultiSocketType.h
@@ -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 ::type next_layer_type_ref;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
- template
- explicit MultiSocketType (Arg& arg, int flags = 0)
+ template
+ 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 SslStream;
typedef SocketWrapperStrand 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 > SslStream;
typedef SocketWrapperStrand 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 m_stream;
ScopedPointer m_ssl_stream; // the ssl portion of our stream if it exists
-
bool m_needsShutdown;
StreamSocket m_next_layer;
-
SSL* m_native_ssl_handle;
};
diff --git a/modules/ripple_asio/sockets/ripple_RippleTlsContext.cpp b/modules/ripple_asio/sockets/ripple_RippleTlsContext.cpp
deleted file mode 100644
index dacb338b54..0000000000
--- a/modules/ripple_asio/sockets/ripple_RippleTlsContext.cpp
+++ /dev/null
@@ -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 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 ();
-}
diff --git a/modules/ripple_asio/sockets/ripple_RippleTlsContext.h b/modules/ripple_asio/sockets/ripple_RippleTlsContext.h
deleted file mode 100644
index 8dc7b8ba9b..0000000000
--- a/modules/ripple_asio/sockets/ripple_RippleTlsContext.h
+++ /dev/null
@@ -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
diff --git a/modules/ripple_core/functional/ripple_Config.cpp b/modules/ripple_core/functional/ripple_Config.cpp
index b4d8ff27b9..fc06448ff4 100644
--- a/modules/ripple_core/functional/ripple_Config.cpp
+++ b/modules/ripple_core/functional/ripple_Config.cpp
@@ -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 (strTemp);
-
if (SectionSingleB (secConfig, SECTION_PEER_PRIVATE, strTemp))
PEER_PRIVATE = lexicalCastThrow (strTemp);
@@ -341,10 +339,21 @@ void Config::load ()
importNodeDatabase = parseKeyValueSection (
secConfig, ConfigSection::importNodeDatabase ());
- if (SectionSingleB (secConfig, SECTION_PEER_PROXY_PORT, strTemp)
- proxyListeningPort = lexicalCastThrow (strTemp);
+ if (SectionSingleB (secConfig, SECTION_PEER_PORT, strTemp))
+ peerListeningPort = lexicalCastThrow (strTemp);
+
+ if (SectionSingleB (secConfig, SECTION_PEER_PROXY_PORT, strTemp))
+ {
+ peerPROXYListeningPort = lexicalCastThrow (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
diff --git a/modules/ripple_core/functional/ripple_Config.h b/modules/ripple_core/functional/ripple_Config.h
index 42d880c6b0..14653e56fd 100644
--- a/modules/ripple_core/functional/ripple_Config.h
+++ b/modules/ripple_core/functional/ripple_Config.h
@@ -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 =
@@ -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;