mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Check file handle limit on startup (RIPD-442, RIPD-1024):
Calculate the number of file descriptors that are needed during execution based on the configuration file, with a hard floor of 1024, adjusting the limit if possible. Refuse to run if enough fds are not available. Additionally, allow administrators to limit the number of incoming connections a configured port will accept. By default no limit is imposed.
This commit is contained in:
@@ -73,7 +73,14 @@ PlainHTTPPeer::PlainHTTPPeer (Port const& port, Handler& handler,
|
||||
void
|
||||
PlainHTTPPeer::run ()
|
||||
{
|
||||
handler_.onAccept (session());
|
||||
if (!handler_.onAccept (session(), remote_address_))
|
||||
{
|
||||
boost::asio::spawn (strand_,
|
||||
std::bind (&PlainHTTPPeer::do_close,
|
||||
shared_from_this()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (! stream_.is_open())
|
||||
return;
|
||||
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
|
||||
#include <ripple/server/Port.h>
|
||||
#include <beast/http/rfc2616.h>
|
||||
#include <beast/module/core/text/LexicalCast.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
bool
|
||||
Port::websockets() const
|
||||
{
|
||||
@@ -159,20 +160,22 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
|
||||
auto const result = section.find("port");
|
||||
if (result.second)
|
||||
{
|
||||
auto const ul = std::stoul(result.first);
|
||||
if (ul > std::numeric_limits<std::uint16_t>::max())
|
||||
try
|
||||
{
|
||||
log << "Value '" << result.first
|
||||
<< "' for key 'port' is out of range\n";
|
||||
Throw<std::exception> ();
|
||||
port.port =
|
||||
beast::lexicalCastThrow<std::uint16_t>(result.first);
|
||||
|
||||
// Port 0 is not supported
|
||||
if (*port.port == 0)
|
||||
Throw<std::exception> ();
|
||||
}
|
||||
if (ul == 0)
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
log <<
|
||||
"Value '0' for key 'port' is invalid\n";
|
||||
Throw<std::exception> ();
|
||||
"Invalid value '" << result.first << "' for key " <<
|
||||
"'port' in [" << section.name() << "]\n";
|
||||
Throw();
|
||||
}
|
||||
port.port = static_cast<std::uint16_t>(ul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +189,26 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const lim = get (section, "limit", "unlimited");
|
||||
|
||||
if (!beast::ci_equal (lim, "unlimited"))
|
||||
{
|
||||
try
|
||||
{
|
||||
port.limit = static_cast<int> (
|
||||
beast::lexicalCastThrow<std::uint16_t>(lim));
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
log <<
|
||||
"Invalid value '" << lim << "' for key " <<
|
||||
"'limit' in [" << section.name() << "]\n";
|
||||
Throw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
populate (section, "admin", log, port.admin_ip, true, {});
|
||||
populate (section, "secure_gateway", log, port.secure_gateway_ip, false,
|
||||
port.admin_ip.get_value_or({}));
|
||||
|
||||
@@ -78,7 +78,14 @@ SSLHTTPPeer::SSLHTTPPeer (Port const& port, Handler& handler,
|
||||
void
|
||||
SSLHTTPPeer::run()
|
||||
{
|
||||
handler_.onAccept (session());
|
||||
if (!handler_.onAccept (session(), remote_address_))
|
||||
{
|
||||
boost::asio::spawn (strand_,
|
||||
std::bind (&SSLHTTPPeer::do_close,
|
||||
shared_from_this()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (! stream_.lowest_layer().is_open())
|
||||
return;
|
||||
|
||||
|
||||
@@ -94,15 +94,22 @@ ServerHandlerImp::onStop()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onAccept (Session& session)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ServerHandlerImp::onAccept (Session& session,
|
||||
boost::asio::ip::tcp::endpoint endpoint)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(countlock_);
|
||||
|
||||
auto const c = ++count_[session.port()];
|
||||
|
||||
if (session.port().limit && c >= session.port().limit)
|
||||
{
|
||||
JLOG (m_journal.trace()) <<
|
||||
session.port().name << " is full; dropping " <<
|
||||
endpoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -188,6 +195,8 @@ void
|
||||
ServerHandlerImp::onClose (Session& session,
|
||||
boost::system::error_code const&)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(countlock_);
|
||||
--count_[session.port()];
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -28,9 +28,16 @@
|
||||
#include <ripple/server/Session.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
#include <ripple/app/main/CollectorManager.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool operator< (Port const& lhs, Port const& rhs)
|
||||
{
|
||||
return lhs.name < rhs.name;
|
||||
}
|
||||
|
||||
// Private implementation
|
||||
class ServerHandlerImp
|
||||
: public ServerHandler
|
||||
@@ -47,6 +54,8 @@ private:
|
||||
beast::insight::Counter rpc_requests_;
|
||||
beast::insight::Event rpc_size_;
|
||||
beast::insight::Event rpc_time_;
|
||||
std::mutex countlock_;
|
||||
std::map<std::reference_wrapper<Port const>, int> count_;
|
||||
|
||||
public:
|
||||
ServerHandlerImp (Application& app, Stoppable& parent,
|
||||
@@ -79,9 +88,6 @@ private:
|
||||
// HTTP::Handler
|
||||
//
|
||||
|
||||
void
|
||||
onAccept (Session& session) override;
|
||||
|
||||
bool
|
||||
onAccept (Session& session,
|
||||
boost::asio::ip::tcp::endpoint endpoint) override;
|
||||
|
||||
Reference in New Issue
Block a user