-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RPC/WS ports to server_info #4427
Conversation
e94932b
to
e0ad966
Compare
e0ad966
to
41c3269
Compare
41c3269
to
41198ea
Compare
Maybe gRPC and peer ports should also be in that list? Still, thanks for tackling this issue, the code looks ok to me, but I don't feel confident to properly review it, so I can only thank you for implementing it in general. :-) |
|
@@ -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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this is because of std::set_intersection
and Elements are compared using operator< and the ranges must be sorted with respect to the same.
Is there a way to static assert that it is sorted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question, and a good idea. Since we're running C++20, std::is_sorted()
is now constexpr
. So, if all of our standard libraries have that support, it should be easy to check at compile time. Otherwise it's still possible to check, but a bit more code to write.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job with the static_assert
. Looks great!
@intelliot This PR introduces a new array in the JSON response. Does it break clients that do not expect the new array? If not, I can remove the checkbox `Breaking change. |
In general adding to a response shouldn’t be considered a breaking change. If you modified an existing field by doing things like changing value type, removing fields, or changing names, these would be breaking changes. |
I added |
@@ -429,7 +429,7 @@ GRPCServerImpl::GRPCServerImpl(Application& app) | |||
// if present, get endpoint from config | |||
if (app_.config().exists("port_grpc")) | |||
{ | |||
Section section = app_.config().section("port_grpc"); | |||
const auto& section = app_.config().section("port_grpc"); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sneak in a minor improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change you made here definitely is an improvement. You're now taking a reference instead of making a copy. And a Section
is a heavy weight thing to copy. Good spotting.
However, not everyone will agree that replacing an explicit type name with auto
is an improvement. In my opinion it hides important information that could be visible explicitly in the source code. My personal opinion is that Herb Sutter was dead wrong when he said "almost always auto
" years ago. So my preferred declaration here would look like...
Section const& section = ...
Folks who use an IDE with something like intellisense sometimes lose track of those of us who who develop code using just a text editor. Explicit type names (as opposed to auto
) also are a big help when viewing code through browsers, like on Github or in code reviews.
I'm not asking for a change here. Just providing a different perspective for you to think about when you make other changes in the future.
bac80f9
to
7cad80a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good! I especially like the new static_assert
. I left a couple of comments, but they are not blockers.
I appreciate that you added the unit test. When I ran code coverage I noticed that here are couple of places in the new code of NetworkOPs.cpp
that are not exercised by the new test. I flagged those areas with comments. It would be really nice if those two places could be exercised as well.
I'm hoping you'll look at how hard it would be to exercise those additional areas in your unit test and add that coverage if the effort is reasonable.
I run code coverage locally on my Mac. I don't know whether you use a Mac or not, but in case it helps, here are the command lines I use to run code coverage locally:
conan install ${SOURCE_DIR} --output-folder . --build missing --settings build_type=Debug
cmake -DCMAKE_BUILD_TYPE=Debug -Dunity=OFF -Dassert=ON -Dwerr=ON -Dwextra=ON -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake ${SOURCE_DIR} -Dcoverage=ON -Dcoverage_core_only=OFF -Ucoverage_test ${SOURCE_DIR}
make -j3 coverage_report
open ./coverage/index.html
src/ripple/app/misc/NetworkOPs.cpp
Outdated
static_assert(std::is_sorted(std::begin(protocols), std::end(protocols))); | ||
{ | ||
Json::Value ports{Json::arrayValue}; | ||
std::vector<std::string> proto; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing that proto
, which is only used inside the for
loop has been lofted out of the loop for a reason.
- I'll guess that you want to avoid re-allocating the vector each time through the loop? If that's the case, consider really avoiding reallocation by calling...
proto.reserve(protocols.size());
before entering the loop.
- However that's a really minor optimization given that there are lots of allocations for
std::string
s and the like taking place in this function. My preference would be to move the declaration ofproto
into the loop just above where it's used in the call tostd::set_intersection()
. That keeps the declaration closest to where it's needed and minimizes the scope ofproto
.
Your call. Neither of these changes is critical. I'm just offering a different perspective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Fixed.
src/ripple/app/misc/NetworkOPs.cpp
Outdated
if (app_.config().exists("port_grpc")) | ||
{ | ||
auto const& grpcSection = app_.config().section("port_grpc"); | ||
auto const optPort = grpcSection.get("port"); | ||
if (optPort && grpcSection.get("ip")) | ||
{ | ||
auto& jv = ports.append(Json::Value(Json::objectValue)); | ||
jv[jss::port] = *optPort; | ||
jv[jss::protocol] = Json::Value{Json::arrayValue}; | ||
jv[jss::protocol].append("port_grpc"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code inside the if (app_.config().exists("port_grpc"))
condition is not exercised by the unit tests. Is there a way to tweak your test to exercise that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I modified my unit tests to cover that case.
if (!admin && | ||
!(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() && | ||
port.admin_user.empty() && port.admin_password.empty())) | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The continue
inside the if (!admin && ...)
condition is not exercised by the unit tests. Is there a way to tweak your test to exercise that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I modified my unit tests to cover that case.
@@ -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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job with the static_assert
. Looks great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good to me. Thanks for the added test coverage!
Suggested commit message:
|
@intelliot Thanks for the suggested commit message. It looks good! |
This is being held until after 1.11 has been released (~June 20) |
* Commits 0b812cd (XRPLF#4427) and 11e914f (XRPLF#4516) conflict. The first added references to `ServerHandlerImp` in files outside of that class's organizational unit (which is technically incorrect). The second removed `ServerHandlerImp`, but was not up to date with develop. This results in the build failing in all circumstances. * Fixes the build by changing references to `ServerHandlerImp` to the more correct `ServerHandler`.
* Commits 0b812cd (#4427) and 11e914f (#4516) conflict. The first added references to `ServerHandlerImp` in files outside of that class's organizational unit (which is technically incorrect). The second removed `ServerHandlerImp`, but was not up to date with develop. This results in the build failing. * Fixes the build by changing references to `ServerHandlerImp` to the more correct `ServerHandler`.
Enhance the /crawl endpoint by publishing WebSocket/RPC ports in the server_info response. The function processing requests to the /crawl endpoint actually calls server_info internally, so this change enables a server to advertise its WebSocket/RPC port(s) to peers via the /crawl endpoint. `grpc` and `peer` ports are included as well. The new `ports` array contains objects, each containing a `port` for the listening port (number string), and an array `protocol` listing the supported protocol(s). This allows crawlers to build a richer topology without needing to port-scan nodes. For non-admin users (including peers), the info about *admin* ports is excluded. Also increase test coverage for RPC ServerInfo. Fix XRPLF#2837.
* Commits 0b812cd (XRPLF#4427) and 11e914f (XRPLF#4516) conflict. The first added references to `ServerHandlerImp` in files outside of that class's organizational unit (which is technically incorrect). The second removed `ServerHandlerImp`, but was not up to date with develop. This results in the build failing. * Fixes the build by changing references to `ServerHandlerImp` to the more correct `ServerHandler`.
Enhance the /crawl endpoint by publishing WebSocket/RPC ports in the server_info response. The function processing requests to the /crawl endpoint actually calls server_info internally, so this change enables a server to advertise its WebSocket/RPC port(s) to peers via the /crawl endpoint. `grpc` and `peer` ports are included as well. The new `ports` array contains objects, each containing a `port` for the listening port (number string), and an array `protocol` listing the supported protocol(s). This allows crawlers to build a richer topology without needing to port-scan nodes. For non-admin users (including peers), the info about *admin* ports is excluded. Also increase test coverage for RPC ServerInfo. Fix XRPLF#2837.
* Commits 0b812cd (XRPLF#4427) and 11e914f (XRPLF#4516) conflict. The first added references to `ServerHandlerImp` in files outside of that class's organizational unit (which is technically incorrect). The second removed `ServerHandlerImp`, but was not up to date with develop. This results in the build failing. * Fixes the build by changing references to `ServerHandlerImp` to the more correct `ServerHandler`.
Enhance the /crawl endpoint by publishing WebSocket/RPC ports in the server_info response. The function processing requests to the /crawl endpoint actually calls server_info internally, so this change enables a server to advertise its WebSocket/RPC port(s) to peers via the /crawl endpoint. `grpc` and `peer` ports are included as well. The new `ports` array contains objects, each containing a `port` for the listening port (number string), and an array `protocol` listing the supported protocol(s). This allows crawlers to build a richer topology without needing to port-scan nodes. For non-admin users (including peers), the info about *admin* ports is excluded. Also increase test coverage for RPC ServerInfo. Fix XRPLF#2837.
* Commits 0b812cd (XRPLF#4427) and 11e914f (XRPLF#4516) conflict. The first added references to `ServerHandlerImp` in files outside of that class's organizational unit (which is technically incorrect). The second removed `ServerHandlerImp`, but was not up to date with develop. This results in the build failing. * Fixes the build by changing references to `ServerHandlerImp` to the more correct `ServerHandler`.
High Level Overview of Change
This PR resolves #2837. It adds info about WebSocket/RPC port(s) of the local
rippled
server to the response ofserver_info
. The function processing requests to the /crawl endpoint actually callsserver_info
internally. Hence, this PR enables arippled
server to advertise info about its WebSocket/RPC port(s) to its peers via the endpoint /crawl. This allows the peers to build a richer topology instead of port-scanning all reachable nodes. For non-admin users (which is true for peers), the extendedserver_info
method does not advertise info about admin RPC/WS poirts.Context of Change
The response of
server_info
includes a new arrayports
. Each array element contains a valueport
for the listening port and an arrayprotocols
for the supported protocol(s). The arrayprotocol
is sorted in increasing order.Type of Change