Format Channelz Address.TcpIpAddress.address as packed bytes (#25629)
* Move address packing to Core
* Format
* Use absl::Base64Escape
* Update src/core/lib/channel/channelz.cc
Co-authored-by: Yash Tibrewal <yashkt@google.com>
Co-authored-by: Yash Tibrewal <yashkt@google.com>
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
index 6f1869c..22279b1 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -19,6 +19,8 @@
#include <grpc/impl/codegen/port_platform.h>
#include "src/core/lib/channel/channelz.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "absl/strings/escaping.h"
#include "absl/strings/strip.h"
@@ -434,12 +436,14 @@
if (!port.empty()) {
port_num = atoi(port.data());
}
- char* b64_host = grpc_base64_encode(host.data(), host.size(), false, false);
+ grpc_resolved_address resolved_host;
+ grpc_string_to_sockaddr(&resolved_host, host.c_str(), port_num);
+ std::string packed_host = grpc_sockaddr_get_packed_host(&resolved_host);
+ std::string b64_host = absl::Base64Escape(packed_host);
data["tcpip_address"] = Json::Object{
{"port", port_num},
{"ip_address", b64_host},
};
- gpr_free(b64_host);
} else if (uri.ok() && uri->scheme() == "unix") {
data["uds_address"] = Json::Object{
{"filename", uri->path()},
diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc
index 692893c..333358a 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -294,3 +294,22 @@
return 0;
}
}
+
+std::string grpc_sockaddr_get_packed_host(
+ const grpc_resolved_address* resolved_addr) {
+ const grpc_sockaddr* addr =
+ reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
+ if (addr->sa_family == GRPC_AF_INET) {
+ const grpc_sockaddr_in* addr4 =
+ reinterpret_cast<const grpc_sockaddr_in*>(addr);
+ const char* addr_bytes = reinterpret_cast<const char*>(&addr4->sin_addr);
+ return std::string(addr_bytes, 4);
+ } else if (addr->sa_family == GRPC_AF_INET6) {
+ const grpc_sockaddr_in6* addr6 =
+ reinterpret_cast<const grpc_sockaddr_in6*>(addr);
+ const char* addr_bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);
+ return std::string(addr_bytes, 16);
+ } else {
+ GPR_ASSERT(false);
+ }
+}
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
index ba91e56..e5297c6 100644
--- a/src/core/lib/iomgr/sockaddr_utils.h
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -77,4 +77,7 @@
int grpc_sockaddr_get_family(const grpc_resolved_address* resolved_addr);
+std::string grpc_sockaddr_get_packed_host(
+ const grpc_resolved_address* resolved_addr);
+
#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py
index 784307a..a500897 100644
--- a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py
+++ b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py
@@ -350,6 +350,15 @@
self.assertEqual(gsc_resp.subchannel.data.calls_succeeded,
gs_resp.socket.data.messages_received)
+ if gs_resp.socket.remote.HasField("tcpip_address"):
+ address = gs_resp.socket.remote.tcpip_address.ip_address
+ self.assertTrue(
+ len(address) == 4 or len(address) == 16, address)
+ if gs_resp.socket.local.HasField("tcpip_address"):
+ address = gs_resp.socket.local.tcpip_address.ip_address
+ self.assertTrue(
+ len(address) == 4 or len(address) == 16, address)
+
def test_streaming_rpc(self):
self._pairs = _generate_channel_server_pairs(1)
# In C++, the argument for _send_successful_stream_stream is message length.
@@ -413,6 +422,7 @@
gs_resp = self._channelz_stub.GetSocket(
channelz_pb2.GetSocketRequest(
socket_id=gss_resp.server[0].listen_socket[0].socket_id))
+
# If the RPC call failed, it will raise a grpc.RpcError
# So, if there is no exception raised, considered pass
diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc
index a9e901e..53f0bf5 100644
--- a/test/cpp/end2end/channelz_service_test.cc
+++ b/test/cpp/end2end/channelz_service_test.cc
@@ -47,6 +47,7 @@
#include <gtest/gtest.h>
+using grpc::channelz::v1::Address;
using grpc::channelz::v1::GetChannelRequest;
using grpc::channelz::v1::GetChannelResponse;
using grpc::channelz::v1::GetServerRequest;
@@ -66,6 +67,14 @@
namespace testing {
namespace {
+static bool ValidateAddress(const Address& address) {
+ if (address.address_case() != Address::kTcpipAddress) {
+ return true;
+ }
+ return address.tcpip_address().ip_address().size() == 4 ||
+ address.tcpip_address().ip_address().size() == 16;
+}
+
// Proxy service supports N backends. Sends RPC to backend dictated by
// request->backend_channel_idx().
class Proxy : public ::grpc::testing::EchoTestService::Service {
@@ -787,6 +796,8 @@
s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
&get_socket_response);
EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+ EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote()));
+ EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local()));
switch (GetParam()) {
case CredentialsType::kInsecure:
EXPECT_FALSE(get_socket_response.socket().has_security());
@@ -898,6 +909,9 @@
s = channelz_stub_->GetSocket(&get_socket_context_1, get_socket_request,
&get_socket_response);
EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
+
+ EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote()));
+ EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local()));
if (listen_socket_size == 2) {
get_socket_request.set_socket_id(
get_server_response.server(0).listen_socket(1).socket_id());