diff --git a/src/ripple/rpc/handlers/AccountLines.cpp b/src/ripple/rpc/handlers/AccountLines.cpp index 2b984476d..ed8cc9618 100644 --- a/src/ripple/rpc/handlers/AccountLines.cpp +++ b/src/ripple/rpc/handlers/AccountLines.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace ripple { @@ -123,25 +124,8 @@ Json::Value doAccountLines (RPC::Context& context) } unsigned int limit; - if (params.isMember (jss::limit)) - { - auto const& jvLimit (params[jss::limit]); - if (! jvLimit.isIntegral ()) - return RPC::expected_field_error (jss::limit, "unsigned integer"); - - limit = jvLimit.isUInt () ? jvLimit.asUInt () : - std::max (0, jvLimit.asInt ()); - - if (context.role != Role::ADMIN) - { - limit = std::max (RPC::Tuning::minLinesPerRequest, - std::min (limit, RPC::Tuning::maxLinesPerRequest)); - } - } - else - { - limit = RPC::Tuning::defaultLinesPerRequest; - } + if (auto err = readLimitField(limit, RPC::Tuning::accountLines, context)) + return *err; Json::Value& jsonLines (result[jss::lines] = Json::arrayValue); VisitData visitData = {{}, accountID, hasPeer, raPeerAccount}; diff --git a/src/ripple/rpc/handlers/AccountObjects.cpp b/src/ripple/rpc/handlers/AccountObjects.cpp index ee61b8c2e..e767feff3 100644 --- a/src/ripple/rpc/handlers/AccountObjects.cpp +++ b/src/ripple/rpc/handlers/AccountObjects.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -107,22 +108,9 @@ Json::Value doAccountObjects (RPC::Context& context) type = iter->second; } - auto limit = RPC::Tuning::defaultObjectsPerRequest; - if (params.isMember (jss::limit)) - { - auto const& jvLimit = params[jss::limit]; - if (! jvLimit.isIntegral ()) - return RPC::expected_field_error (jss::limit, "unsigned integer"); - - limit = jvLimit.isUInt () ? jvLimit.asUInt () : - std::max (0, jvLimit.asInt ()); - - if (context.role != Role::ADMIN) - { - limit = std::max (RPC::Tuning::minObjectsPerRequest, - std::min (limit, RPC::Tuning::maxObjectsPerRequest)); - } - } + unsigned int limit; + if (auto err = readLimitField(limit, RPC::Tuning::accountObjects, context)) + return *err; uint256 dirIndex; uint256 entryIndex; diff --git a/src/ripple/rpc/handlers/AccountOffers.cpp b/src/ripple/rpc/handlers/AccountOffers.cpp index 39c1afb65..e7c134c69 100644 --- a/src/ripple/rpc/handlers/AccountOffers.cpp +++ b/src/ripple/rpc/handlers/AccountOffers.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace ripple { @@ -81,25 +82,8 @@ Json::Value doAccountOffers (RPC::Context& context) return rpcError (rpcACT_NOT_FOUND); unsigned int limit; - if (params.isMember (jss::limit)) - { - auto const& jvLimit (params[jss::limit]); - if (! jvLimit.isIntegral ()) - return RPC::expected_field_error (jss::limit, "unsigned integer"); - - limit = jvLimit.isUInt () ? jvLimit.asUInt () : - std::max (0, jvLimit.asInt ()); - - if (context.role != Role::ADMIN) - { - limit = std::max (RPC::Tuning::minOffersPerRequest, - std::min (limit, RPC::Tuning::maxOffersPerRequest)); - } - } - else - { - limit = RPC::Tuning::defaultOffersPerRequest; - } + if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context)) + return *err; Json::Value& jsonOffers (result[jss::offers] = Json::arrayValue); std::vector > offers; diff --git a/src/ripple/rpc/handlers/BookOffers.cpp b/src/ripple/rpc/handlers/BookOffers.cpp index c36f86f83..fa58b7b0d 100644 --- a/src/ripple/rpc/handlers/BookOffers.cpp +++ b/src/ripple/rpc/handlers/BookOffers.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace ripple { @@ -171,21 +172,9 @@ Json::Value doBookOffers (RPC::Context& context) return RPC::make_error (rpcBAD_MARKET); } - unsigned int iLimit; - if (context.params.isMember (jss::limit)) - { - auto const& jvLimit (context.params[jss::limit]); - - if (! jvLimit.isIntegral ()) - return RPC::expected_field_error (jss::limit, "unsigned integer"); - - iLimit = jvLimit.isUInt () ? jvLimit.asUInt () : - std::max (0, jvLimit.asInt ()); - } - else - { - iLimit = 0; - } + unsigned int limit; + if (auto err = readLimitField(limit, RPC::Tuning::bookOffers, context)) + return *err; bool const bProof (context.params.isMember (jss::proof)); @@ -197,7 +186,7 @@ Json::Value doBookOffers (RPC::Context& context) context.role == Role::ADMIN, lpLedger, {{pay_currency, pay_issuer}, {get_currency, get_issuer}}, - takerID ? *takerID : zero, bProof, iLimit, jvMarker, jvResult); + takerID ? *takerID : zero, bProof, limit, jvMarker, jvResult); context.loadType = Resource::feeMediumBurdenRPC; diff --git a/src/ripple/rpc/handlers/NoRippleCheck.cpp b/src/ripple/rpc/handlers/NoRippleCheck.cpp index 3ecf0f5ee..578335f36 100644 --- a/src/ripple/rpc/handlers/NoRippleCheck.cpp +++ b/src/ripple/rpc/handlers/NoRippleCheck.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace ripple { @@ -74,20 +75,9 @@ Json::Value doNoRippleCheck (RPC::Context& context) return RPC::invalid_field_message ("role"); } - unsigned int limit = 300; - if (params.isMember (jss::limit)) - { - auto const& jvLimit (params[jss::limit]); - if (! jvLimit.isIntegral ()) - return RPC::expected_field_error ("limit", "unsigned integer"); - limit = jvLimit.isUInt () ? jvLimit.asUInt () : - std::max (0, jvLimit.asInt ()); - if (context.role != Role::ADMIN) - { - limit = std::max (RPC::Tuning::minLinesPerRequest, - std::min (limit, RPC::Tuning::maxLinesPerRequest)); - } - } + unsigned int limit; + if (auto err = readLimitField(limit, RPC::Tuning::noRippleCheck, context)) + return *err; bool transactions = false; if (params.isMember (jss::transactions)) diff --git a/src/ripple/rpc/impl/Tuning.h b/src/ripple/rpc/impl/Tuning.h index 687799fa9..0dab69028 100644 --- a/src/ripple/rpc/impl/Tuning.h +++ b/src/ripple/rpc/impl/Tuning.h @@ -27,50 +27,25 @@ namespace RPC { /** @{ */ namespace Tuning { -/** Default account objects returned per request from the - account_objects command when no limit param is specified -*/ -static unsigned int const defaultObjectsPerRequest (200); +/** Represents RPC limit parameter values that have a min, default and max. */ +struct LimitRange { + unsigned int rmin, rdefault, rmax; +}; -/** Minimum account objects returned per request from the - account_objects command. Specified in the limit param. -*/ -static unsigned int const minObjectsPerRequest (10); +/** Limits for the account_lines command. */ +static LimitRange const accountLines = {10, 200, 400}; -/** Maximum account objects returned per request from the - account_objects command. Specified in the limit param. -*/ -static unsigned int const maxObjectsPerRequest (400); +/** Limits for the account_objects command. */ +static LimitRange const accountObjects = {10, 200, 400}; -/** Default account lines returned per request from the - account_lines command when no limit param is specified -*/ -static unsigned int const defaultLinesPerRequest (200); +/** Limits for the account_offers command. */ +static LimitRange const accountOffers = {10, 200, 400}; -/** Minimum account lines returned per request from the - account_lines command. Specified in the limit param. -*/ -static unsigned int const minLinesPerRequest (10); +/** Limits for the book_offers command. */ +static LimitRange const bookOffers = {0, 0, 400}; -/** Maximum account lines returned per request from the - account_lines command. Specified in the limit param. -*/ -static unsigned int const maxLinesPerRequest (400); - -/** Default offers returned per request from the - account_offers command when no limit param is specified. -*/ -static unsigned int const defaultOffersPerRequest (200); - -/** Minimum offers returned per request from the - account_offers command. Specified in the limit param. -*/ -static unsigned int const minOffersPerRequest (10); - -/** Maximum offers returned per request from the - account_lines command. Specified in the limit param. -*/ -static unsigned int const maxOffersPerRequest (400); +/** Limits for the no_ripple_check command. */ +static LimitRange const noRippleCheck = {10, 300, 400}; static int const defaultAutoFillFeeMultiplier (10); static int const maxPathfindsInProgress (2); diff --git a/src/ripple/rpc/impl/Utilities.cpp b/src/ripple/rpc/impl/Utilities.cpp index 0942436e5..b0eee111a 100644 --- a/src/ripple/rpc/impl/Utilities.cpp +++ b/src/ripple/rpc/impl/Utilities.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -94,5 +96,23 @@ injectSLE (Json::Value& jv, } } +boost::optional readLimitField( + unsigned int& limit, + Tuning::LimitRange const& range, + Context const& context) +{ + limit = range.rdefault; + if (auto const& jvLimit = context.params[jss::limit]) + { + if (! (jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0))) + return RPC::expected_field_error (jss::limit, "unsigned integer"); + + limit = jvLimit.asUInt(); + if (context.role != Role::ADMIN) + limit = std::max(range.rmin, std::min(range.rmax, limit)); + } + return boost::none; +} + } // ripple } // RPC diff --git a/src/ripple/rpc/impl/Utilities.h b/src/ripple/rpc/impl/Utilities.h index 144c9ba11..5bcbfc5ae 100644 --- a/src/ripple/rpc/impl/Utilities.h +++ b/src/ripple/rpc/impl/Utilities.h @@ -22,6 +22,7 @@ #include #include +#include namespace Json { class Value; @@ -52,6 +53,13 @@ void injectSLE (Json::Value& jv, SLE const& sle); +/** Retrieve the limit value from a Context, or set a default - + then restrict the limit by max and min if not an ADMIN request. + + If there is an error, return it as JSON. */ +boost::optional readLimitField( + unsigned int& limit, Tuning::LimitRange const&, Context const&); + } // RPC } // ripple