From d34c0e6a451f1d1b0cf4a4f17fcc156ea2833cce Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 21 Dec 2012 07:38:51 -0800 Subject: [PATCH] Make running out of file descriptors non fatal. Fix a bug that kills the RPC door if it gets a prohibited connection --- src/cpp/ripple/PeerDoor.cpp | 23 +++++++++++++++---- src/cpp/ripple/PeerDoor.h | 1 + src/cpp/ripple/RPCDoor.cpp | 29 +++++++++++++++++++----- src/cpp/ripple/RPCDoor.h | 4 +++- src/cpp/websocketpp/src/roles/server.hpp | 14 ++++++++---- 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/cpp/ripple/PeerDoor.cpp b/src/cpp/ripple/PeerDoor.cpp index 947dca9f69..e65e72d7ef 100644 --- a/src/cpp/ripple/PeerDoor.cpp +++ b/src/cpp/ripple/PeerDoor.cpp @@ -9,6 +9,9 @@ #include "Application.h" #include "Config.h" #include "utils.h" +#include "Log.h" + +SETUP_LOG(); using namespace std; using namespace boost::asio::ip; @@ -21,7 +24,7 @@ static DH* handleTmpDh(SSL* ssl, int is_export, int iKeyLength) PeerDoor::PeerDoor(boost::asio::io_service& io_service) : mAcceptor(io_service, tcp::endpoint(address().from_string(theConfig.PEER_IP), theConfig.PEER_PORT)), - mCtx(boost::asio::ssl::context::sslv23) + mCtx(boost::asio::ssl::context::sslv23), mDelayTimer(io_service) { mCtx.set_options( boost::asio::ssl::context::default_workarounds @@ -32,7 +35,7 @@ PeerDoor::PeerDoor(boost::asio::io_service& io_service) : if (1 != SSL_CTX_set_cipher_list(mCtx.native_handle(), theConfig.PEER_SSL_CIPHER_LIST.c_str())) std::runtime_error("Error setting cipher list (no valid ciphers)."); - cerr << "Peer port: " << theConfig.PEER_IP << " " << theConfig.PEER_PORT << endl; + Log(lsINFO) << "Peer port: " << theConfig.PEER_IP << " " << theConfig.PEER_PORT; startListening(); } @@ -50,13 +53,25 @@ void PeerDoor::startListening() void PeerDoor::handleConnect(Peer::pointer new_connection, const boost::system::error_code& error) { + bool delay = false; if (!error) { new_connection->connected(error); } - else cerr << "Error: " << error; + else + { + if (error == boost::system::errc::too_many_files_open) + delay = true; + cLog(lsERROR) << error; + } - startListening(); + if (delay) + { + mDelayTimer.expires_from_now(boost::posix_time::milliseconds(500)); + mDelayTimer.async_wait(boost::bind(&PeerDoor::startListening, this)); + } + else + startListening(); } void initSSLContext(boost::asio::ssl::context& context, diff --git a/src/cpp/ripple/PeerDoor.h b/src/cpp/ripple/PeerDoor.h index ac472ee0e9..9ea247152c 100644 --- a/src/cpp/ripple/PeerDoor.h +++ b/src/cpp/ripple/PeerDoor.h @@ -18,6 +18,7 @@ class PeerDoor private: boost::asio::ip::tcp::acceptor mAcceptor; boost::asio::ssl::context mCtx; + boost::asio::deadline_timer mDelayTimer; void startListening(); void handleConnect(Peer::pointer new_connection, const boost::system::error_code& error); diff --git a/src/cpp/ripple/RPCDoor.cpp b/src/cpp/ripple/RPCDoor.cpp index 40c1e0f676..b52e675f53 100644 --- a/src/cpp/ripple/RPCDoor.cpp +++ b/src/cpp/ripple/RPCDoor.cpp @@ -11,11 +11,13 @@ using namespace std; using namespace boost::asio::ip; RPCDoor::RPCDoor(boost::asio::io_service& io_service) : - mAcceptor(io_service, tcp::endpoint(address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT)) + mAcceptor(io_service, tcp::endpoint(address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT)), + mDelayTimer(io_service) { cLog(lsINFO) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE; startListening(); } + RPCDoor::~RPCDoor() { cLog(lsINFO) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE; @@ -33,27 +35,42 @@ void RPCDoor::startListening() bool RPCDoor::isClientAllowed(const std::string& ip) { - if (theConfig.RPC_ALLOW_REMOTE) return(true); - if (ip=="127.0.0.1") return(true); + if (theConfig.RPC_ALLOW_REMOTE) + return true; + if (ip == "127.0.0.1") + return true; - return(false); + return false; } void RPCDoor::handleConnect(RPCServer::pointer new_connection, const boost::system::error_code& error) { + bool delay = false; if (!error) { // Restrict callers by IP if (!isClientAllowed(new_connection->getSocket().remote_endpoint().address().to_string())) { + startListening(); return; } new_connection->connected(); } - else cLog(lsINFO) << "RPCDoor::handleConnect Error: " << error; + else + { + if (error == boost::system::errc::too_many_files_open) + delay = true; + cLog(lsINFO) << "RPCDoor::handleConnect Error: " << error; + } - startListening(); + if (delay) + { + mDelayTimer.expires_from_now(boost::posix_time::milliseconds(1000)); + mDelayTimer.async_wait(boost::bind(&RPCDoor::startListening, this)); + } + else + startListening(); } // vim:ts=4 diff --git a/src/cpp/ripple/RPCDoor.h b/src/cpp/ripple/RPCDoor.h index ab60539c67..b1e01e2e33 100644 --- a/src/cpp/ripple/RPCDoor.h +++ b/src/cpp/ripple/RPCDoor.h @@ -7,7 +7,9 @@ Handles incoming connections from people making RPC Requests class RPCDoor { - boost::asio::ip::tcp::acceptor mAcceptor; + boost::asio::ip::tcp::acceptor mAcceptor; + boost::asio::deadline_timer mDelayTimer; + void startListening(); void handleConnect(RPCServer::pointer new_connection, const boost::system::error_code& error); diff --git a/src/cpp/websocketpp/src/roles/server.hpp b/src/cpp/websocketpp/src/roles/server.hpp index 3399355802..e256a5d44c 100644 --- a/src/cpp/websocketpp/src/roles/server.hpp +++ b/src/cpp/websocketpp/src/roles/server.hpp @@ -388,6 +388,8 @@ template void server::handle_accept(connection_ptr con, const boost::system::error_code& error) { + bool delay = false; + boost::lock_guard lock(m_endpoint.m_lock); try @@ -398,10 +400,8 @@ void server::handle_accept(connection_ptr con, if (error == boost::system::errc::too_many_files_open) { con->m_fail_reason = "too many files open"; + delay = true; - // TODO: make this configurable - //m_timer.expires_from_now(boost::posix_time::milliseconds(1000)); - //m_timer.async_wait(boost::bind(&type::start_accept,this)); } else if (error == boost::asio::error::operation_aborted) { con->m_fail_reason = "io_service operation canceled"; @@ -426,7 +426,13 @@ void server::handle_accept(connection_ptr con, << "handle_accept caught exception: " << e.what() << log::endl; } - this->start_accept(); + if (delay) + { // Don't spin if too many files are open DJS + m_timer.expires_from_now(boost::posix_time::milliseconds(500)); + m_timer.async_wait(boost::bind(&type::start_accept,this)); + } + else + this->start_accept(); } // server::connection Implimentation