aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc14
-rw-r--r--src/core/lib/channel/channelz.cc77
-rw-r--r--src/core/lib/channel/channelz.h42
-rw-r--r--src/core/lib/gpr/string.cc45
-rw-r--r--src/core/lib/gpr/string.h3
5 files changed, 159 insertions, 22 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 5168e4555e..0179831328 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -397,11 +397,14 @@ static bool read_channel_args(grpc_chttp2_transport* t,
}
}
if (channelz_enabled) {
+ grpc_core::channelz::SocketAddress remote;
+ grpc_core::channelz::SocketAddress local;
char* host = nullptr;
int port_num = -1;
// try to pick out just the host port (maybe trims off scheme prefix).
grpc_uri* uri = grpc_uri_parse(t->peer_string, true);
// if peer string was a valid URI, we can use our lib to do the trimming.
+ // TODO(ncteisen): handle UDS address.
if (uri != nullptr) {
const char* host_port = uri->path;
if (*host_port == '/') ++host_port;
@@ -410,15 +413,22 @@ static bool read_channel_args(grpc_chttp2_transport* t,
if (port != nullptr) {
port_num = atoi(port);
}
+ remote.set_blob(gpr_string_base64_encode(host));
+ remote.set_port(port_num);
+ remote.set_type(
+ grpc_core::channelz::SocketAddress::AddressType::kTcpAddress);
+ gpr_free(host);
gpr_free(port);
} else {
// if peer string is not a valid URI, just use the entire string to
// surface that info.
- host = gpr_strdup(t->peer_string);
+ remote.set_blob(gpr_strdup(t->peer_string));
+ remote.set_type(grpc_core::channelz::SocketAddress::AddressType::
+ kDirectChannelAddress);
}
t->channelz_socket =
grpc_core::MakeRefCounted<grpc_core::channelz::SocketNode>(
- grpc_core::UniquePtr<char>(host), port_num);
+ std::move(local), std::move(remote));
grpc_uri_destroy(uri);
}
return enable_bdp;
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
index 6da8a172b5..d8c826c54d 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -277,10 +277,65 @@ grpc_json* ServerNode::RenderJson() {
return top_level_json;
}
-SocketNode::SocketNode(UniquePtr<char> remote_host, int remote_port)
+SocketAddress::SocketAddress() : type_(AddressType::kUnset), port_(-1) {}
+
+SocketAddress::SocketAddress(SocketAddress&& other) {
+ type_ = other.type_;
+ port_ = other.port_;
+ blob_.reset((other.blob_.release()));
+}
+
+void SocketAddress::PopulateJson(const char* name, grpc_json* json) {
+ if (type_ == AddressType::kUnset) {
+ return;
+ }
+ grpc_json* json_iterator = nullptr;
+ json_iterator = grpc_json_create_child(json_iterator, json, name, nullptr,
+ GRPC_JSON_OBJECT, false);
+ json = json_iterator;
+ json_iterator = nullptr;
+ switch (type_) {
+ case AddressType::kTcpAddress:
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "tcpip_address", nullptr,
+ GRPC_JSON_OBJECT, false);
+ json = json_iterator;
+ json_iterator = nullptr;
+ json_iterator =
+ grpc_json_add_number_string_child(json, json_iterator, "port", port_);
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "ip_address", blob_.get(),
+ GRPC_JSON_STRING, false);
+ break;
+ case AddressType::kUdsAddress:
+ json_iterator = grpc_json_create_child(json_iterator, json, "uds_address",
+ nullptr, GRPC_JSON_OBJECT, false);
+ json = json_iterator;
+ json_iterator = nullptr;
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "filename", blob_.get(),
+ GRPC_JSON_STRING, false);
+ break;
+ case AddressType::kDirectChannelAddress:
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "other_address", nullptr,
+ GRPC_JSON_OBJECT, false);
+ json = json_iterator;
+ json_iterator = nullptr;
+ json_iterator = grpc_json_create_child(
+ json_iterator, json, "name", blob_.get(), GRPC_JSON_STRING, false);
+ break;
+ break;
+ default:
+ GPR_UNREACHABLE_CODE(GPR_ASSERT(0));
+ break;
+ }
+}
+
+SocketNode::SocketNode(SocketAddress local, SocketAddress remote)
: BaseNode(EntityType::kSocket),
- remote_host_(std::move(remote_host)),
- remote_port_(remote_port) {}
+ local_(std::move(local)),
+ remote_(std::move(remote)) {}
void SocketNode::RecordStreamStartedFromLocal() {
gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast<gpr_atm>(1));
@@ -319,20 +374,8 @@ grpc_json* SocketNode::RenderJson() {
json_iterator = grpc_json_add_number_string_child(json, json_iterator,
"socketId", uuid());
json = top_level_json;
- json_iterator = nullptr;
- json_iterator = grpc_json_create_child(json_iterator, json, "remote", nullptr,
- GRPC_JSON_OBJECT, false);
- json = json_iterator;
- json_iterator = nullptr;
- json_iterator = grpc_json_create_child(json_iterator, json, "tcpip_address",
- nullptr, GRPC_JSON_OBJECT, false);
- json = json_iterator;
- json_iterator = nullptr;
- json_iterator = grpc_json_add_number_string_child(json, json_iterator, "port",
- remote_port_);
- json_iterator =
- grpc_json_create_child(json_iterator, json, "ip_address",
- remote_host_.get(), GRPC_JSON_STRING, false);
+ remote_.PopulateJson("remote", json);
+ local_.PopulateJson("local", json);
// reset json iterators to top level object
json = top_level_json;
json_iterator = nullptr;
diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h
index 404d8341ff..70efbd861d 100644
--- a/src/core/lib/channel/channelz.h
+++ b/src/core/lib/channel/channelz.h
@@ -229,10 +229,45 @@ class ServerNode : public BaseNode {
ChannelTrace trace_;
};
+// helper class for holding and rendering the information about a particular
+// socket's address
+class SocketAddress {
+ public:
+ enum class AddressType {
+ kUnset,
+ kTcpAddress,
+ kUdsAddress,
+ kDirectChannelAddress,
+ };
+
+ SocketAddress();
+ SocketAddress(SocketAddress&& other);
+
+ void PopulateJson(const char* name, grpc_json* json);
+
+ void set_blob(char* blob) { blob_.reset(blob); }
+ void set_port(int port) { port_ = port; }
+ void set_type(AddressType type) { type_ = type; }
+
+ const char* blob_view() { return blob_.get(); }
+ int port() { return port_; }
+ AddressType type() { return type_; }
+
+ private:
+ AddressType type_;
+ // this holds different information for different address types:
+ // kTcpAddress = host
+ // kUdsAddress = filename
+ // kDirectChannelAddress = name (which is fd num)
+ UniquePtr<char> blob_;
+ // used for kTcpAddress, otherwise -1
+ int port_;
+};
+
// Handles channelz bookkeeping for sockets
class SocketNode : public BaseNode {
public:
- SocketNode(UniquePtr<char> remote_host, int remote_port);
+ SocketNode(SocketAddress local, SocketAddress remote);
~SocketNode() override {}
grpc_json* RenderJson() override;
@@ -262,14 +297,15 @@ class SocketNode : public BaseNode {
gpr_atm last_remote_stream_created_millis_ = 0;
gpr_atm last_message_sent_millis_ = 0;
gpr_atm last_message_received_millis_ = 0;
- UniquePtr<char> remote_host_;
- int remote_port_;
+ SocketAddress local_;
+ SocketAddress remote_;
};
// Handles channelz bookkeeping for listen sockets
class ListenSocketNode : public BaseNode {
public:
// ListenSocketNode takes ownership of host.
+ // TODO(ncteisen): use SocketAddress to support more address types.
ListenSocketNode(UniquePtr<char> host, int port);
~ListenSocketNode() override {}
diff --git a/src/core/lib/gpr/string.cc b/src/core/lib/gpr/string.cc
index 0a76fc1f54..5672b7a2b9 100644
--- a/src/core/lib/gpr/string.cc
+++ b/src/core/lib/gpr/string.cc
@@ -156,6 +156,51 @@ int gpr_parse_bytes_to_uint32(const char* buf, size_t len, uint32_t* result) {
return 1;
}
+static const char alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const uint8_t tail_xtra[3] = {0, 2, 3};
+
+char* gpr_string_base64_encode(const char* in) {
+ size_t in_len = strlen(in);
+ size_t in_triplets = in_len / 3;
+ size_t tail_case = in_len % 3;
+ size_t out_length = in_triplets * 4 + tail_xtra[tail_case];
+ char* output = static_cast<char*>(gpr_malloc(out_length + 1));
+ char* out = output;
+ size_t i;
+
+ /* encode full triplets */
+ for (i = 0; i < in_triplets; i++) {
+ out[0] = alphabet[in[0] >> 2];
+ out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
+ out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
+ out[3] = alphabet[in[2] & 0x3f];
+ out += 4;
+ in += 3;
+ }
+
+ /* encode the remaining bytes */
+ switch (tail_case) {
+ case 0:
+ break;
+ case 1:
+ out[0] = alphabet[in[0] >> 2];
+ out[1] = alphabet[(in[0] & 0x3) << 4];
+ out += 2;
+ in += 1;
+ break;
+ case 2:
+ out[0] = alphabet[in[0] >> 2];
+ out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
+ out[2] = alphabet[(in[1] & 0xf) << 2];
+ out += 3;
+ in += 2;
+ break;
+ }
+ out[0] = '\0';
+ return output;
+}
+
void gpr_reverse_bytes(char* str, int len) {
char *p1, *p2;
for (p1 = str, p2 = str + len - 1; p2 > p1; ++p1, --p2) {
diff --git a/src/core/lib/gpr/string.h b/src/core/lib/gpr/string.h
index ce51fe4632..1bb50196e8 100644
--- a/src/core/lib/gpr/string.h
+++ b/src/core/lib/gpr/string.h
@@ -41,6 +41,9 @@ char* gpr_dump(const char* buf, size_t len, uint32_t flags);
int gpr_parse_bytes_to_uint32(const char* data, size_t length,
uint32_t* result);
+/* returns allocated string with the base64 encoding of in */
+char* gpr_string_base64_encode(const char* in);
+
/* Minimum buffer size for calling ltoa */
#define GPR_LTOA_MIN_BUFSIZE (3 * sizeof(long))