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:
Nik Bougalis
2016-04-08 09:39:09 -07:00
parent 79ca82c078
commit 47eb4da080
25 changed files with 265 additions and 88 deletions

View File

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

View File

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

View File

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

View File

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

View File

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