From 41198eab1ccaa5270b75b744cda69c4e8cb1d7af Mon Sep 17 00:00:00 2001 From: Long Le Date: Fri, 17 Feb 2023 17:02:32 +0100 Subject: [PATCH] Add RPC/WebSocket ports to server_info (#4427) Fix #2837. --- src/ripple/app/main/Application.cpp | 7 ++++++ src/ripple/app/main/Application.h | 3 +++ src/ripple/app/misc/NetworkOPs.cpp | 33 +++++++++++++++++++++++++++++ src/ripple/protocol/jss.h | 5 +++-- src/test/rpc/ServerInfo_test.cpp | 32 +++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index dce11bc38f0..56ddd5029b7 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -602,6 +602,13 @@ class ApplicationImp : public Application, public BasicApp return *m_networkOPs; } + virtual ServerHandlerImp& + getServerHandler() override + { + assert(serverHandler_); + return *serverHandler_; + } + boost::asio::io_service& getIOService() override { diff --git a/src/ripple/app/main/Application.h b/src/ripple/app/main/Application.h index d8cb7d31815..d2ba8f7cc75 100644 --- a/src/ripple/app/main/Application.h +++ b/src/ripple/app/main/Application.h @@ -89,6 +89,7 @@ class Overlay; class PathRequests; class PendingSaves; class PublicKey; +class ServerHandlerImp; class SecretKey; class STLedgerEntry; class TimeKeeper; @@ -231,6 +232,8 @@ class Application : public beast::PropertyStream::Source getOPs() = 0; virtual OrderBookDB& getOrderBookDB() = 0; + virtual ServerHandlerImp& + getServerHandler() = 0; virtual TransactionMaster& getMasterTransaction() = 0; virtual perf::PerfLog& diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 610b8e71adc..bf7c41bb590 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -2661,6 +2662,38 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) info["reporting"] = app_.getReportingETL().getInfo(); } + // This array must be sorted in increasing order. + static constexpr std::array protocols{ + "http", "https", "ws", "ws2", "wss", "wss2"}; + { + Json::Value ports{Json::arrayValue}; + std::vector proto; + for (auto const& port : app_.getServerHandler().setup().ports) + { + // Don't publish admin ports for non-admin users + if (!admin && + !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() && + port.admin_user.empty() && port.admin_password.empty())) + continue; + proto.clear(); + std::set_intersection( + std::begin(port.protocol), + std::end(port.protocol), + std::begin(protocols), + std::end(protocols), + std::back_inserter(proto)); + if (!proto.empty()) + { + auto& jv = ports.append(Json::Value(Json::objectValue)); + jv[jss::port] = std::to_string(port.port); + jv[jss::protocol] = Json::Value{Json::arrayValue}; + for (auto const& p : proto) + jv[jss::protocol].append(p); + } + } + info[jss::ports] = std::move(ports); + } + return info; } diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index 01e30dd9327..490d4ff3760 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -459,13 +459,14 @@ JSS(peers); // out: InboundLedger, handlers/Peers, Overlay JSS(peer_disconnects); // Severed peer connection counter. JSS(peer_disconnects_resources); // Severed peer connections because of // excess resource consumption. -JSS(port); // in: Connect +JSS(port); // in: Connect, out: NetworkOPs +JSS(ports); // out: NetworkOPs JSS(previous); // out: Reservations JSS(previous_ledger); // out: LedgerPropose JSS(proof); // in: BookOffers JSS(propose_seq); // out: LedgerPropose JSS(proposers); // out: NetworkOPs, LedgerConsensus -JSS(protocol); // out: PeerImp +JSS(protocol); // out: NetworkOPs, PeerImp JSS(proxied); // out: RPC ping JSS(pubkey_node); // out: NetworkOPs JSS(pubkey_publisher); // out: ValidatorList diff --git a/src/test/rpc/ServerInfo_test.cpp b/src/test/rpc/ServerInfo_test.cpp index 24cfd12299a..17a77d1a21e 100644 --- a/src/test/rpc/ServerInfo_test.cpp +++ b/src/test/rpc/ServerInfo_test.cpp @@ -77,8 +77,16 @@ class ServerInfo_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result].isMember(jss::info)); } + { - Env env(*this, makeValidatorConfig()); + auto config = makeValidatorConfig(); + auto const rpc_port = + (*config)["port_rpc"].get("port"); + auto const ws_port = (*config)["port_ws"].get("port"); + BEAST_EXPECT(rpc_port); + BEAST_EXPECT(ws_port); + + Env env(*this, std::move(config)); auto const result = env.rpc("server_info"); BEAST_EXPECT(!result[jss::result].isMember(jss::error)); BEAST_EXPECT(result[jss::result][jss::status] == "success"); @@ -86,6 +94,28 @@ class ServerInfo_test : public beast::unit_test::suite BEAST_EXPECT( result[jss::result][jss::info][jss::pubkey_validator] == validator_data::public_key); + + auto const& ports = result[jss::result][jss::info][jss::ports]; + BEAST_EXPECT(ports.isArray()); + BEAST_EXPECT(ports.size() == 2); + for (auto const& port : ports) + { + auto const& proto = port[jss::protocol]; + BEAST_EXPECT(proto.isArray()); + auto const p = port[jss::port].asUInt(); + BEAST_EXPECT(p == rpc_port || p == ws_port); + if (p == rpc_port) + { + BEAST_EXPECT(proto.size() == 2); + BEAST_EXPECT(proto[0u].asString() == "http"); + BEAST_EXPECT(proto[1u].asString() == "ws2"); + } + if (p == ws_port) + { + BEAST_EXPECT(proto.size() == 1); + BEAST_EXPECT(proto[0u].asString() == "ws"); + } + } } }