20#include <xrpld/app/main/GRPCServer.h>
21#include <xrpld/core/ConfigSections.h>
22#include <xrpl/beast/core/CurrentThreadName.h>
23#include <xrpl/beast/net/IPAddressConversion.h>
24#include <xrpl/resource/Fees.h>
42 peerClean = peer.
substr(first + 1);
58template <
class Request,
class Response>
60 org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService& service,
61 grpc::ServerCompletionQueue& cq,
74 , bindListener_(
std::move(bindListener))
75 , handler_(
std::move(handler))
77 , requiredCondition_(
std::move(requiredCondition))
78 , loadType_(
std::move(loadType))
79 , secureGatewayIPs_(secureGatewayIPs)
86template <
class Request,
class Response>
90 return std::make_shared<CallData<Request, Response>>(
102template <
class Request,
class Response>
107 BOOST_ASSERT(!finished_);
110 this->shared_from_this();
125 thisShared->process(coro);
132 grpc::StatusCode::INTERNAL,
"Job Queue is already stopped"};
133 responder_.FinishWithError(status,
this);
137template <
class Request,
class Response>
144 auto usage = getUsage();
149 grpc::StatusCode::RESOURCE_EXHAUSTED,
150 "usage balance exceeds threshold"};
151 responder_.FinishWithError(status,
this);
155 auto loadType = getLoadType();
156 usage.charge(loadType);
161 toLog <<
"role = " << (int)role;
163 toLog <<
" address = ";
164 if (
auto clientIp = getClientIpAddress())
165 toLog << clientIp.value();
168 if (
auto user = getUser())
169 toLog << user.value();
197 grpc::StatusCode::FAILED_PRECONDITION,
199 responder_.FinishWithError(status,
this);
205 responder_.Finish(result.
first, result.
second,
this);
211 grpc::Status status{grpc::StatusCode::INTERNAL, ex.
what()};
212 responder_.FinishWithError(status,
this);
216template <
class Request,
class Response>
223template <
class Request,
class Response>
230template <
class Request,
class Response>
240template <
class Request,
class Response>
244 if (
auto descriptor = Request::GetDescriptor()->FindFieldByName(
"user"))
247 Request::GetReflection()->GetString(request_, descriptor);
256template <
class Request,
class Response>
260 auto endpoint = getClientEndpoint();
262 return endpoint->address();
266template <
class Request,
class Response>
270 return ripple::getEndpoint(ctx_.peer());
273template <
class Request,
class Response>
279 auto clientIp = getClientIpAddress();
291template <
class Request,
class Response>
299 if (
auto descriptor =
300 Response::GetDescriptor()->FindFieldByName(
"is_unlimited"))
302 Response::GetReflection()->SetBool(&response, descriptor,
true);
307template <
class Request,
class Response>
311 auto endpoint = getClientEndpoint();
315 Throw<std::runtime_error>(
"Failed to get client endpoint");
326 auto const optIp = section.
get(
"ip");
330 auto const optPort = section.
get(
"port");
335 boost::asio::ip::tcp::endpoint endpoint(
336 boost::asio::ip::make_address(*optIp),
std::stoi(*optPort));
344 JLOG(
journal_.
error()) <<
"Error setting grpc server address";
345 Throw<std::runtime_error>(
"Error setting grpc server address");
348 auto const optSecureGateway = section.
get(
"secure_gateway");
349 if (optSecureGateway)
357 boost::algorithm::trim(ip);
358 auto const addr = boost::asio::ip::make_address(ip);
360 if (addr.is_unspecified())
363 <<
"Can't pass unspecified IP in "
364 <<
"secure_gateway section of port_grpc";
365 Throw<std::runtime_error>(
366 "Unspecified IP in secure_gateway section");
375 <<
"Error parsing secure gateway IPs for grpc server";
376 Throw<std::runtime_error>(
377 "Error parsing secure_gateway section");
402 JLOG(
journal_.
debug()) <<
"Completion Queue has been shutdown";
418 return sPtr.get() == ptr;
420 BOOST_ASSERT(it != requests.
end());
421 it->swap(requests.
back());
441 while (
cq_->Next(&tag, &ok))
445 <<
" ptr = " << ptr <<
" ok = " << ok;
450 <<
"Request listener cancelled. " <<
"Destroying object";
455 if (!ptr->isFinished())
457 JLOG(
journal_.
debug()) <<
"Received new request. Processing";
460 auto cloned = ptr->clone();
467 JLOG(
journal_.
debug()) <<
"Sent response. Destroying object";
481 auto addToRequests = [&requests](
auto callData) {
487 org::xrpl::rpc::v1::GetLedgerRequest,
488 org::xrpl::rpc::v1::GetLedgerResponse>;
490 addToRequests(std::make_shared<cd>(
494 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
497 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedger,
504 org::xrpl::rpc::v1::GetLedgerDataRequest,
505 org::xrpl::rpc::v1::GetLedgerDataResponse>;
507 addToRequests(std::make_shared<cd>(
511 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
512 RequestGetLedgerData,
514 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerData,
521 org::xrpl::rpc::v1::GetLedgerDiffRequest,
522 org::xrpl::rpc::v1::GetLedgerDiffResponse>;
524 addToRequests(std::make_shared<cd>(
528 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
529 RequestGetLedgerDiff,
531 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerDiff,
538 org::xrpl::rpc::v1::GetLedgerEntryRequest,
539 org::xrpl::rpc::v1::GetLedgerEntryResponse>;
541 addToRequests(std::make_shared<cd>(
545 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
546 RequestGetLedgerEntry,
548 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerEntry,
565 grpc::ServerBuilder builder;
570 builder.AddListeningPort(
577 cq_ = builder.AddCompletionQueue();
579 server_ = builder.BuildAndStart();
585boost::asio::ip::tcp::endpoint
590 return boost::asio::ip::tcp::endpoint(
622 XRPL_ASSERT(!
running_,
"ripple::GRPCServer::~GRPCServer : is not running");
625boost::asio::ip::tcp::endpoint
constexpr const char * c_str() const
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Stream trace() const
Severity stream access functions.
virtual Config & config()=0
virtual beast::Journal journal(std::string const &name)=0
virtual JobQueue & getJobQueue()=0
virtual Resource::Manager & getResourceManager()=0
virtual NetworkOPs & getOPs()=0
virtual LedgerMaster & getLedgerMaster()=0
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Section & section(std::string const &name)
Returns the section with the given name.
Resource::Consumer getUsage()
std::optional< std::string > getUser()
grpc::ServerCompletionQueue & cq_
Resource::Charge getLoadType()
void setIsUnlimited(Response &response, bool isUnlimited)
std::optional< boost::asio::ip::address > getClientIpAddress()
BindListener< Request, Response > bindListener_
grpc::ServerAsyncResponseWriter< Response > responder_
Role getRole(bool isUnlimited)
std::shared_ptr< Processor > clone() override
CallData(org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService &service, grpc::ServerCompletionQueue &cq, Application &app, BindListener< Request, Response > bindListener, Handler< Request, Response > handler, Forward< Request, Response > forward, RPC::Condition requiredCondition, Resource::Charge loadType, std::vector< boost::asio::ip::address > const &secureGatewayIPs)
std::optional< boost::asio::ip::tcp::endpoint > getClientEndpoint()
org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService & service_
virtual void process() override
virtual bool isFinished() override
std::string serverAddress_
std::vector< std::shared_ptr< Processor > > setupListeners()
std::unique_ptr< grpc::Server > server_
std::unique_ptr< grpc::ServerCompletionQueue > cq_
org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService service_
GRPCServerImpl(Application &app)
static unsigned constexpr apiVersion
boost::asio::ip::tcp::endpoint getEndpoint() const
std::vector< boost::asio::ip::address > secureGatewayIPs_
std::uint16_t serverPort_
boost::asio::ip::tcp::endpoint getEndpoint() const
std::shared_ptr< InfoSub > pointer
std::shared_ptr< Coro > postCoro(JobType t, std::string const &name, F &&f)
Creates a coroutine and adds a job to the queue which will run it.
An endpoint that consumes resources.
virtual Consumer newInboundEndpoint(beast::IP::Endpoint const &address)=0
Create a new endpoint keyed by inbound IP address or the forwarded IP if proxied.
Holds a collection of configuration values.
std::optional< T > get(std::string const &name) const
T emplace_back(T... args)
T find_first_of(T... args)
T find_last_of(T... args)
boost::asio::ip::tcp::endpoint to_asio_endpoint(Endpoint const &endpoint)
Convert to asio::ip::tcp::endpoint.
Endpoint from_asio(boost::asio::ip::address const &address)
Convert to Endpoint.
void setCurrentThreadName(std::string_view newThreadName)
Changes the name of the caller thread.
error_code_i conditionMet(Condition condition_required, T &context)
ErrorInfo const & get_error_info(error_code_i code)
Returns an ErrorInfo that reflects the error code.
Charge const feeMediumBurdenRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
std::pair< org::xrpl::rpc::v1::GetLedgerResponse, grpc::Status > doLedgerGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerRequest > &context)
std::pair< org::xrpl::rpc::v1::GetLedgerEntryResponse, grpc::Status > doLedgerEntryGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerEntryRequest > &context)
void erase(STObject &st, TypedField< U > const &f)
Remove a field in an STObject.
Role
Indicates the level of administrative permission to grant.
std::pair< org::xrpl::rpc::v1::GetLedgerDiffResponse, grpc::Status > doLedgerDiffGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerDiffRequest > &context)
std::pair< org::xrpl::rpc::v1::GetLedgerDataResponse, grpc::Status > doLedgerDataGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerDataRequest > &context)
Maps an rpc error code to its token, default message, and HTTP status.
Json::StaticString message