xrpld
Loading...
Searching...
No Matches
GRPCServer.cpp
1#include <xrpld/app/main/GRPCServer.h>
2
3#include <xrpld/app/main/Application.h>
4#include <xrpld/rpc/Context.h>
5#include <xrpld/rpc/GRPCHandlers.h>
6#include <xrpld/rpc/Role.h>
7#include <xrpld/rpc/detail/Handler.h>
8
9#include <xrpl/basics/FileUtilities.h>
10#include <xrpl/basics/Log.h>
11#include <xrpl/basics/contract.h>
12#include <xrpl/beast/core/CurrentThreadName.h>
13#include <xrpl/beast/net/IPAddressConversion.h>
14#include <xrpl/beast/net/IPEndpoint.h>
15#include <xrpl/beast/utility/instrumentation.h>
16#include <xrpl/config/BasicConfig.h>
17#include <xrpl/config/Constants.h>
18#include <xrpl/core/Job.h>
19#include <xrpl/core/JobQueue.h>
20#include <xrpl/protocol/ErrorCodes.h>
21#include <xrpl/resource/Charge.h>
22#include <xrpl/resource/Consumer.h>
23#include <xrpl/resource/Fees.h>
24#include <xrpl/server/InfoSub.h>
25
26#include <boost/algorithm/string/trim.hpp>
27#include <boost/asio/ip/address.hpp>
28#include <boost/asio/ip/tcp.hpp>
29#include <boost/icl/interval_set.hpp>
30
31#include <grpc/grpc_security_constants.h>
32#include <grpcpp/completion_queue.h>
33#include <grpcpp/security/server_credentials.h>
34#include <grpcpp/server_builder.h>
35#include <grpcpp/support/status.h>
36#include <org/xrpl/rpc/v1/get_ledger.pb.h>
37#include <org/xrpl/rpc/v1/get_ledger_data.pb.h>
38#include <org/xrpl/rpc/v1/get_ledger_diff.pb.h>
39#include <org/xrpl/rpc/v1/get_ledger_entry.pb.h>
40#include <org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
41
42#include <algorithm>
43#include <cstddef>
44#include <cstdint>
45#include <exception>
46#include <memory>
47#include <optional>
48#include <sstream>
49#include <stdexcept>
50#include <string>
51#include <utility>
52#include <vector>
53
54namespace xrpl {
55
56namespace {
57
58// helper function. converts string to endpoint. handles ipv4 and ipv6, with or
59// without port, with or without prepended scheme
60std::optional<boost::asio::ip::tcp::endpoint>
61getEndpoint(std::string const& peer)
62{
63 try
64 {
65 std::size_t const first = peer.find_first_of(':');
66 std::size_t const last = peer.find_last_of(':');
67 std::string peerClean(peer);
68 if (first != last)
69 {
70 peerClean = peer.substr(first + 1);
71 }
72
73 std::optional<beast::IP::Endpoint> endpoint =
75 if (endpoint)
76 return beast::IP::toAsioEndpoint(endpoint.value());
77 }
78 catch (std::exception const&) // NOLINT(bugprone-empty-catch)
79 {
80 }
81 return {};
82}
83
84} // namespace
85
86template <class Request, class Response>
88 org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService& service,
89 grpc::ServerCompletionQueue& cq,
90 Application& app,
94 RPC::Condition requiredCondition,
95 Resource::Charge loadType,
96 std::vector<boost::asio::ip::address> const& secureGatewayIPs)
97 : service_(service)
98 , cq_(cq)
99 , finished_(false)
100 , app_(app)
101 , responder_(&ctx_)
102 , bindListener_(std::move(bindListener))
103 , handler_(std::move(handler))
104 , forward_(std::move(forward))
105 , requiredCondition_(requiredCondition)
106 , loadType_(std::move(loadType))
107 , secureGatewayIPs_(secureGatewayIPs)
108{
109 // Bind a listener. When a request is received, "this" will be returned
110 // from CompletionQueue::Next
112}
113
114template <class Request, class Response>
129
130template <class Request, class Response>
131void
133{
134 // sanity check
135 BOOST_ASSERT(!finished_);
136
138
139 // Need to set finished to true before processing the response,
140 // because as soon as the response is posted to the completion
141 // queue (via responder_.Finish(...) or responder_.FinishWithError(...)),
142 // the CallData object is returned as a tag in handleRpcs().
143 // handleRpcs() checks the finished variable, and if true, destroys
144 // the object. Setting finished to true before calling process
145 // ensures that finished is always true when this CallData object
146 // is returned as a tag in handleRpcs(), after sending the response
147 finished_ = true;
148 auto coro = app_.getJobQueue().postCoro(
149 JobType::JtRpc, "gRPC-Client", [thisShared](std::shared_ptr<JobQueue::Coro> coro) {
150 thisShared->process(coro);
151 });
152
153 // If coro is null, then the JobQueue has already been shutdown
154 if (!coro)
155 {
156 grpc::Status const status{grpc::StatusCode::INTERNAL, "Job Queue is already stopped"};
157 responder_.FinishWithError(status, this);
158 }
159}
160
161template <class Request, class Response>
162void
164{
165 try
166 {
167 auto usage = getUsage();
168 bool const isUnlimited = clientIsUnlimited();
169 if (!isUnlimited && usage.disconnect(app_.getJournal("gRPCServer")))
170 {
171 grpc::Status const status{
172 grpc::StatusCode::RESOURCE_EXHAUSTED, "usage balance exceeds threshold"};
173 responder_.FinishWithError(status, this);
174 }
175 else
176 {
177 auto loadType = getLoadType();
178 usage.charge(loadType);
179 auto role = getRole(isUnlimited);
180
181 {
182 std::stringstream toLog;
183 toLog << "role = " << (int)role;
184
185 toLog << " address = ";
186 if (auto clientIp = getClientIpAddress())
187 toLog << clientIp.value();
188
189 toLog << " user = ";
190 if (auto user = getUser())
191 toLog << user.value();
192 toLog << " isUnlimited = " << isUnlimited;
193
194 JLOG(app_.getJournal("GRPCServer::Calldata").debug()) << toLog.str();
195 }
196
198 {app_.getJournal("gRPCServer"),
199 app_,
200 loadType,
201 app_.getOPs(),
202 app_.getLedgerMaster(),
203 usage,
204 role,
205 coro,
208 request_};
209
210 // Make sure we can currently handle the rpc
211 ErrorCodeI const conditionMetRes = RPC::conditionMet(requiredCondition_, context);
212
213 if (conditionMetRes != RpcSuccess)
214 {
215 RPC::ErrorInfo const errorInfo = RPC::getErrorInfo(conditionMetRes);
216 grpc::Status const status{
217 grpc::StatusCode::FAILED_PRECONDITION, errorInfo.message.cStr()};
218 responder_.FinishWithError(status, this);
219 }
220 else
221 {
224 responder_.Finish(result.first, result.second, this);
225 }
226 }
227 }
228 catch (std::exception const& ex)
229 {
230 grpc::Status const status{grpc::StatusCode::INTERNAL, ex.what()};
231 responder_.FinishWithError(status, this);
232 }
233}
234
235template <class Request, class Response>
236bool
241
242template <class Request, class Response>
248
249template <class Request, class Response>
250Role
252{
253 if (isUnlimited)
254 {
255 return Role::IDENTIFIED;
256 }
257
258 return Role::USER;
259}
260
261template <class Request, class Response>
264{
265 if (auto descriptor = Request::GetDescriptor()->FindFieldByName("user"))
266 {
267 std::string user = Request::GetReflection()->GetString(request_, descriptor);
268 if (!user.empty())
269 {
270 return user;
271 }
272 }
273 return {};
274}
275
276template <class Request, class Response>
279{
280 auto endpoint = getClientEndpoint();
281 if (endpoint)
282 return endpoint->address();
283 return {};
284}
285
286template <class Request, class Response>
289{
290 return xrpl::getEndpoint(ctx_.peer());
291}
292
293template <class Request, class Response>
294bool
296{
297 if (!getUser())
298 return false;
299 auto clientIp = getClientIpAddress();
300 if (clientIp)
301 {
302 for (auto& ip : secureGatewayIPs_)
303 {
304 if (ip == clientIp)
305 return true;
306 }
307 }
308 return false;
309}
310
311template <class Request, class Response>
312void
314{
315 if (isUnlimited)
316 {
317 if (auto descriptor = Response::GetDescriptor()->FindFieldByName("is_unlimited"))
318 {
319 Response::GetReflection()->SetBool(&response, descriptor, true);
320 }
321 }
322}
323
324template <class Request, class Response>
327{
328 auto endpoint = getClientEndpoint();
329 if (endpoint)
330 return app_.getResourceManager().newInboundEndpoint(beast::IP::fromAsio(endpoint.value()));
331 Throw<std::runtime_error>("Failed to get client endpoint");
332}
333
335 : app_(app), journal_(app_.getJournal("gRPC Server"))
336{
337 // if present, get endpoint from config
338 if (app_.config().exists(Sections::kPortGrpc))
339 {
340 Section const& section = app_.config().section(Sections::kPortGrpc);
341
342 auto const optIp = section.get(Keys::kIp);
343 if (!optIp)
344 return;
345
346 auto const optPort = section.get(Keys::kPort);
347 if (!optPort)
348 return;
349 try
350 {
351 boost::asio::ip::tcp::endpoint const endpoint(
352 boost::asio::ip::make_address(*optIp), std::stoi(*optPort));
353
354 std::stringstream ss;
355 ss << endpoint;
356 serverAddress_ = ss.str();
357 }
358 catch (std::exception const&)
359 {
360 JLOG(journal_.error()) << "Error setting grpc server address";
361 Throw<std::runtime_error>("Error setting grpc server address");
362 }
363
364 auto const optSecureGateway = section.get(Keys::kSecureGateway);
365 if (optSecureGateway)
366 {
367 try
368 {
369 std::stringstream ss{*optSecureGateway};
370 std::string ip;
371 while (std::getline(ss, ip, ','))
372 {
373 boost::algorithm::trim(ip);
374 auto const addr = boost::asio::ip::make_address(ip);
375
376 if (addr.is_unspecified())
377 {
378 JLOG(journal_.error()) << "Can't pass unspecified IP in "
379 << "secure_gateway section of port_grpc";
380 Throw<std::runtime_error>("Unspecified IP in secure_gateway section");
381 }
382
383 secureGatewayIPs_.emplace_back(addr);
384 }
385 }
386 catch (std::exception const&)
387 {
388 JLOG(journal_.error()) << "Error parsing secure gateway IPs for grpc server";
389 Throw<std::runtime_error>("Error parsing secure_gateway section");
390 }
391 }
392
393 // Read TLS certificate configuration (optional)
394 sslCertPath_ = section.get(Keys::kSslCert);
395 sslKeyPath_ = section.get(Keys::kSslKey);
398
399 // If cert or key is specified, both must be specified
400 if (sslCertPath_.has_value() || sslKeyPath_.has_value())
401 {
402 if (!sslCertPath_.has_value() || !sslKeyPath_.has_value())
403 {
404 JLOG(journal_.error())
405 << "Both ssl_cert and ssl_key must be specified for gRPC TLS";
406 Throw<std::runtime_error>("Incomplete TLS configuration for gRPC");
407 }
408 JLOG(journal_.info()) << "gRPC TLS enabled with certificate: " << *sslCertPath_;
409 }
410
411 // Validate TLS configuration consistency: ssl_cert_chain only makes sense when TLS is
412 // enabled
413 if (sslCertChainPath_.has_value() &&
414 (!sslCertPath_.has_value() || !sslKeyPath_.has_value()))
415 {
416 JLOG(journal_.error())
417 << "ssl_cert_chain specified for gRPC without both ssl_cert and ssl_key; "
418 << "this is an invalid TLS configuration";
419 Throw<std::runtime_error>(
420 "Invalid gRPC TLS configuration: ssl_cert_chain requires both ssl_cert and "
421 "ssl_key");
422 }
423
424 // Validate TLS configuration consistency: ssl_client_ca only makes sense when TLS is
425 // enabled
426 if (sslClientCAPath_.has_value() && (!sslCertPath_.has_value() || !sslKeyPath_.has_value()))
427 {
428 JLOG(journal_.error())
429 << "ssl_client_ca specified for gRPC without both ssl_cert and ssl_key; "
430 << "this is an invalid TLS configuration";
431 Throw<std::runtime_error>(
432 "Invalid gRPC TLS configuration: ssl_client_ca requires both ssl_cert and ssl_key");
433 }
434 }
435}
436
437void
439{
440 JLOG(journal_.debug()) << "Shutting down";
441
442 // The below call cancels all "listeners" (CallData objects that are waiting
443 // for a request, as opposed to processing a request), and blocks until all
444 // requests being processed are completed. CallData objects in the midst of
445 // processing requests need to actually send data back to the client, via
446 // responder_.Finish(...) or responder_.FinishWithError(...), for this call
447 // to unblock. Each cancelled listener is returned via cq_.Next(...) with ok
448 // set to false
449 server_->Shutdown();
450 JLOG(journal_.debug()) << "Server has been shutdown";
451
452 // Always shutdown the completion queue after the server. This call allows
453 // cq_.Next() to return false, once all events posted to the completion
454 // queue have been processed. See handleRpcs() for more details.
455 cq_->Shutdown();
456 JLOG(journal_.debug()) << "Completion Queue has been shutdown";
457}
458
459void
461{
462 // This collection should really be an unordered_set. However, to delete
463 // from the unordered_set, we need a shared_ptr, but cq_.Next() (see below
464 // while loop) sets the tag to a raw pointer.
466
467 auto erase = [&requests](Processor* ptr) {
468 auto it = std::ranges::find_if(
469 requests, [ptr](std::shared_ptr<Processor>& sPtr) { return sPtr.get() == ptr; });
470 BOOST_ASSERT(it != requests.end());
471 it->swap(requests.back());
472 requests.pop_back();
473 };
474
475 void* tag = nullptr; // uniquely identifies a request.
476 bool ok = false;
477 // Block waiting to read the next event from the completion queue. The
478 // event is uniquely identified by its tag, which in this case is the
479 // memory address of a CallData instance.
480 // The return value of Next should always be checked. This return value
481 // tells us whether there is any kind of event or cq_ is shutting down.
482 // When cq_.Next(...) returns false, all work has been completed and the
483 // loop can exit. When the server is shutdown, each CallData object that is
484 // listening for a request is forcibly cancelled, and is returned by
485 // cq_->Next() with ok set to false. Then, each CallData object processing
486 // a request must complete (by sending data to the client), each of which
487 // will be returned from cq_->Next() with ok set to true. After all
488 // cancelled listeners and all CallData objects processing requests are
489 // returned via cq_->Next(), cq_->Next() will return false, causing the
490 // loop to exit.
491 while (cq_->Next(&tag, &ok))
492 {
493 auto ptr = static_cast<Processor*>(tag);
494 JLOG(journal_.trace()) << "Processing CallData object."
495 << " ptr = " << ptr << " ok = " << ok;
496
497 if (!ok)
498 {
499 JLOG(journal_.debug()) << "Request listener cancelled. "
500 << "Destroying object";
501 erase(ptr);
502 }
503 else
504 {
505 if (!ptr->isFinished())
506 {
507 JLOG(journal_.debug()) << "Received new request. Processing";
508 // ptr is now processing a request, so create a new CallData
509 // object to handle additional requests
510 auto cloned = ptr->clone();
511 requests.push_back(cloned);
512 // process the request
513 ptr->process();
514 }
515 else
516 {
517 JLOG(journal_.debug()) << "Sent response. Destroying object";
518 erase(ptr);
519 }
520 }
521 }
522 JLOG(journal_.debug()) << "Completion Queue drained";
523}
524
525// create a CallData instance for each RPC
528{
529 using RPC::Condition;
531
532 auto addToRequests = [&requests](auto callData) { requests.push_back(std::move(callData)); };
533
534 {
535 using cd =
537
538 addToRequests(
540 service_,
541 *cq_,
542 app_,
543 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedger,
545 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedger,
546 Condition::NoCondition,
549 }
550 {
551 using cd = CallData<
552 org::xrpl::rpc::v1::GetLedgerDataRequest,
553 org::xrpl::rpc::v1::GetLedgerDataResponse>;
554
555 addToRequests(
557 service_,
558 *cq_,
559 app_,
560 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerData,
562 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerData,
563 Condition::NoCondition,
566 }
567 {
568 using cd = CallData<
569 org::xrpl::rpc::v1::GetLedgerDiffRequest,
570 org::xrpl::rpc::v1::GetLedgerDiffResponse>;
571
572 addToRequests(
574 service_,
575 *cq_,
576 app_,
577 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerDiff,
579 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerDiff,
580 Condition::NoCondition,
583 }
584 {
585 using cd = CallData<
586 org::xrpl::rpc::v1::GetLedgerEntryRequest,
587 org::xrpl::rpc::v1::GetLedgerEntryResponse>;
588
589 addToRequests(
591 service_,
592 *cq_,
593 app_,
594 &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerEntry,
596 &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerEntry,
597 Condition::NoCondition,
600 }
601 return requests;
602}
603
606{
607 if (not sslCertPath_.has_value() or not sslKeyPath_.has_value())
608 {
609 JLOG(journal_.info()) << "Configuring gRPC server without TLS";
610 return grpc::InsecureServerCredentials();
611 }
612
613 JLOG(journal_.info()) << "Configuring gRPC server with TLS";
614
615 try
616 {
617 boost::system::error_code ec;
618 grpc::SslServerCredentialsOptions sslOpts;
619 grpc::SslServerCredentialsOptions::PemKeyCertPair keyCertPair;
620
621 std::string const certContents = getFileContents(ec, *sslCertPath_);
622 if (ec)
623 {
624 JLOG(journal_.error()) << "Failed to read gRPC SSL certificate file: " << *sslCertPath_
625 << " - " << ec.message(); // LCOV_EXCL_LINE
626 return nullptr;
627 }
628
629 std::string const keyContents = getFileContents(ec, *sslKeyPath_);
630 if (ec)
631 {
632 JLOG(journal_.error()) << "Failed to read gRPC SSL key file: " << *sslKeyPath_ << " - "
633 << ec.message(); // LCOV_EXCL_LINE
634 return nullptr;
635 }
636
637 keyCertPair.private_key = keyContents;
638
639 // Read intermediate CA certificates for server certificate chain (optional)
640 std::string certChainContents;
641 if (sslCertChainPath_.has_value())
642 {
643 certChainContents = getFileContents(ec, *sslCertChainPath_);
644 if (ec)
645 {
646 JLOG(journal_.error())
647 << "Failed to read gRPC SSL cert chain file: " << *sslCertChainPath_ << " - "
648 << ec.message(); // LCOV_EXCL_LINE
649 return nullptr;
650 }
651 }
652
653 // Read CA certificate for client verification (mTLS, optional)
654 if (sslClientCAPath_.has_value())
655 {
656 auto const clientCAContents = getFileContents(ec, *sslClientCAPath_);
657 if (ec)
658 {
659 JLOG(journal_.error())
660 << "Failed to read gRPC SSL client CA file: " << *sslClientCAPath_ << " - "
661 << ec.message(); // LCOV_EXCL_LINE
662 return nullptr;
663 }
664
665 if (clientCAContents.empty())
666 {
667 JLOG(journal_.error())
668 << "Empty/truncated gRPC SSL client CA file: " << *sslClientCAPath_
669 << " - failed to configure mutual TLS"; // LCOV_EXCL_LINE
670 return nullptr;
671 }
672
673 sslOpts.pem_root_certs = clientCAContents;
674 sslOpts.client_certificate_request =
675 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
676 JLOG(journal_.info()) << "gRPC mutual TLS enabled - client certificates will be "
677 "required and verified";
678 }
679
680 // Combine server cert with intermediate CA certs for complete chain
681 keyCertPair.cert_chain = certContents;
682 if (!certChainContents.empty())
683 {
684 keyCertPair.cert_chain += '\n' + certChainContents;
685 JLOG(journal_.info()) << "gRPC server certificate chain configured with "
686 "intermediate CA certificates"; // LCOV_EXCL_LINE
687 }
688
689 sslOpts.pem_key_cert_pairs.push_back(keyCertPair);
690
691 JLOG(journal_.info()) << "gRPC TLS credentials configured successfully"; // LCOV_EXCL_LINE
692 return grpc::SslServerCredentials(sslOpts);
693 }
694 catch (std::exception const& e)
695 {
696 JLOG(journal_.error()) << "Exception while configuring gRPC TLS: "
697 << e.what(); // LCOV_EXCL_LINE
698 return nullptr;
699 }
700}
701
702bool
704{
705 // if config does not specify a grpc server address, don't start
706 if (serverAddress_.empty())
707 return false;
708
709 // Determine TLS mode for logging
710 bool const tlsEnabled = sslCertPath_.has_value() && sslKeyPath_.has_value();
711 bool const mtlsEnabled = tlsEnabled && sslClientCAPath_.has_value();
712
713 std::string tlsMode = "without TLS";
714 if (mtlsEnabled)
715 {
716 tlsMode = "with mutual TLS (mTLS)";
717 }
718 else if (tlsEnabled)
719 {
720 tlsMode = "with TLS";
721 }
722
723 JLOG(journal_.info()) << "Starting gRPC server at " << serverAddress_ << " "
724 << tlsMode; // LCOV_EXCL_LINE
725
726 grpc::ServerBuilder builder;
727 int port = 0;
728
729 // Create credentials (TLS or insecure) based on configuration
731 if (!credentials)
732 {
733 JLOG(journal_.error()) << "Failed to create gRPC server credentials for " << serverAddress_
734 << " (TLS mode: " << tlsMode
735 << ") - server will not start"; // LCOV_EXCL_LINE
736 return false;
737 }
738
739 // Add listening port with appropriate credentials
740 builder.AddListeningPort(serverAddress_, credentials, &port);
741
742 // Register "service_" as the instance through which we'll communicate with
743 // clients. In this case it corresponds to an *asynchronous* service.
744 builder.RegisterService(&service_);
745
746 // Get hold of the completion queue used for the asynchronous communication
747 // with the gRPC runtime.
748 cq_ = builder.AddCompletionQueue();
749
750 // Finally assemble the server.
751 server_ = builder.BuildAndStart();
752 serverPort_ = static_cast<std::uint16_t>(port);
753
754 if (serverPort_ != 0u)
755 {
756 JLOG(journal_.info()) << "gRPC server started successfully on port " << serverPort_;
757 }
758 else
759 {
760 JLOG(journal_.error())
761 << "Failed to start gRPC server at " << serverAddress_ << " (TLS mode: " << tlsMode
762 << "); Possible causes: address already in use, invalid address format, or permission "
763 "denied"; // LCOV_EXCL_LINE
764 }
765
766 return static_cast<bool>(serverPort_);
767}
768
769boost::asio::ip::tcp::endpoint
771{
772 std::string const addr = serverAddress_.substr(0, serverAddress_.find_last_of(':'));
773 return boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(addr), serverPort_);
774}
775
776bool
778{
779 // Start the server and setup listeners
780 if (running_ = impl_.start(); running_)
781 {
782 thread_ = std::thread([this]() {
783 // Start the event loop and begin handling requests
784 beast::setCurrentThreadName("xrpld: grpc");
785 this->impl_.handleRpcs();
786 });
787 }
788 return running_;
789}
790
791void
793{
794 if (running_)
795 {
796 impl_.shutdown();
797 thread_.join();
798 running_ = false;
799 }
800}
801
803{
804 XRPL_ASSERT(!running_, "xrpl::GRPCServer::~GRPCServer : is not running");
805}
806
807boost::asio::ip::tcp::endpoint
809{
810 return impl_.getEndpoint();
811}
812
813} // namespace xrpl
T back(T... args)
static std::optional< Endpoint > fromStringChecked(std::string const &s)
Create an Endpoint from a string.
constexpr char const * cStr() const
Definition json_value.h:57
Forward< Request, Response > forward_
Definition GRPCServer.h:178
Resource::Consumer getUsage()
std::vector< boost::asio::ip::address > const & secureGatewayIPs_
Definition GRPCServer.h:186
std::optional< boost::asio::ip::address > getClientIpAddress()
org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService & service_
Definition GRPCServer.h:146
Handler< Request, Response > handler_
Definition GRPCServer.h:175
RPC::Condition requiredCondition_
Definition GRPCServer.h:181
std::optional< std::string > getUser()
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)
BindListener< Request, Response > bindListener_
Definition GRPCServer.h:172
Role getRole(bool isUnlimited)
Resource::Charge getLoadType()
std::optional< boost::asio::ip::tcp::endpoint > getClientEndpoint()
grpc::ServerAsyncResponseWriter< Response > responder_
Definition GRPCServer.h:169
std::shared_ptr< Processor > clone() override
void setIsUnlimited(Response &response, bool isUnlimited)
grpc::ServerCompletionQueue & cq_
Definition GRPCServer.h:149
grpc::ServerContext ctx_
Definition GRPCServer.h:154
std::uint16_t serverPort_
Definition GRPCServer.h:65
Application & app_
Definition GRPCServer.h:62
std::optional< std::string > sslKeyPath_
Definition GRPCServer.h:71
std::optional< std::string > sslCertPath_
Definition GRPCServer.h:70
std::function< grpc::Status( org::xrpl::rpc::v1::XRPLedgerAPIService::Stub *, grpc::ClientContext *, Request, Response *)> Forward
Definition GRPCServer.h:99
std::function< std::pair< Response, grpc::Status >(RPC::GRPCContext< Request > &)> Handler
Definition GRPCServer.h:94
std::vector< boost::asio::ip::address > secureGatewayIPs_
Definition GRPCServer.h:67
std::optional< std::string > sslCertChainPath_
Definition GRPCServer.h:72
std::unique_ptr< grpc::ServerCompletionQueue > cq_
Definition GRPCServer.h:53
std::vector< std::shared_ptr< Processor > > setupListeners()
std::optional< std::string > sslClientCAPath_
Definition GRPCServer.h:74
GRPCServerImpl(Application &app)
beast::Journal journal_
Definition GRPCServer.h:76
std::unique_ptr< grpc::Server > server_
Definition GRPCServer.h:60
boost::asio::ip::tcp::endpoint getEndpoint() const
std::string serverAddress_
Definition GRPCServer.h:64
org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService service_
Definition GRPCServer.h:58
std::function< void( org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService &, grpc::ServerContext *, Request *, grpc::ServerAsyncResponseWriter< Response > *, grpc::CompletionQueue *, grpc::ServerCompletionQueue *, void *)> BindListener
Definition GRPCServer.h:82
static constexpr unsigned kApiVersion
Definition GRPCServer.h:96
std::shared_ptr< grpc::ServerCredentials > createServerCredentials()
std::thread thread_
Definition GRPCServer.h:313
boost::asio::ip::tcp::endpoint getEndpoint() const
GRPCServerImpl impl_
Definition GRPCServer.h:312
std::shared_ptr< InfoSub > pointer
Definition InfoSub.h:47
A consumption charge.
Definition Charge.h:9
An endpoint that consumes resources.
Definition Consumer.h:15
T empty(T... args)
T end(T... args)
T find_first_of(T... args)
T find_if(T... args)
T find_last_of(T... args)
T get(T... args)
T getline(T... args)
T make_shared(T... args)
boost::asio::ip::tcp::endpoint toAsioEndpoint(Endpoint const &endpoint)
Convert to asio::ip::tcp::endpoint.
Endpoint fromAsio(boost::asio::ip::address const &address)
Convert to Endpoint.
void setCurrentThreadName(std::string_view newThreadName)
Changes the name of the caller thread.
STL namespace.
ErrorCodeI conditionMet(Condition conditionRequired, T &context)
Definition Handler.h:58
ErrorInfo const & getErrorInfo(ErrorCodeI code)
Returns an ErrorInfo that reflects the error code.
Charge const kFeeMediumBurdenRpc
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
ErrorCodeI
Definition ErrorCodes.h:22
@ RpcSuccess
Definition ErrorCodes.h:26
std::string getFileContents(boost::system::error_code &ec, boost::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
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)
Role
Indicates the level of administrative permission to grant.
Definition Role.h:24
@ IDENTIFIED
Definition Role.h:24
@ USER
Definition Role.h:24
std::pair< org::xrpl::rpc::v1::GetLedgerResponse, grpc::Status > doLedgerGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerRequest > &context)
@ JtRpc
Definition Job.h:33
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.
Definition STExchange.h:148
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition Role.cpp:115
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T pop_back(T... args)
T push_back(T... args)
T str(T... args)
static constexpr auto kSslCertChain
Definition Constants.h:158
static constexpr auto kSslKey
Definition Constants.h:162
static constexpr auto kSslClientCa
Definition Constants.h:161
static constexpr auto kSslCert
Definition Constants.h:157
static constexpr auto kSecureGateway
Definition Constants.h:151
Maps an rpc error code to its token, default message, and HTTP status.
Definition ErrorCodes.h:172
json::StaticString message
Definition ErrorCodes.h:191
static constexpr auto kPortGrpc
Definition Constants.h:44
T substr(T... args)
T value(T... args)
T what(T... args)