[Lldb-commits] [lldb] [lldb] For a host socket, add a method to print the listening address. (PR #118330)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Mon Dec 2 10:06:56 PST 2024
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/118330
This is most useful if you are listening on an address like 'localhost:0' and want to know the resolved ip + port of the socket listener.
>From c3226b620bc8f745b92b3aca7b189803a24db788 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Mon, 2 Dec 2024 08:29:01 -0800
Subject: [PATCH] [lldb] For a host socket, add a method to print the listening
address.
This is most useful if you are listening on an address like 'localhost:0' and want to know the resolved ip + port of the socket listeniner.
---
lldb/include/lldb/Host/Socket.h | 3 ++
lldb/include/lldb/Host/common/TCPSocket.h | 2 +
lldb/include/lldb/Host/posix/DomainSocket.h | 2 +
lldb/source/Host/common/TCPSocket.cpp | 22 +++++++--
lldb/source/Host/posix/DomainSocket.cpp | 17 ++++++-
lldb/unittests/Host/SocketTest.cpp | 51 ++++++++++++++++++---
6 files changed, 86 insertions(+), 11 deletions(-)
diff --git a/lldb/include/lldb/Host/Socket.h b/lldb/include/lldb/Host/Socket.h
index e98797b36c8a5d..c937e0c02ff19e 100644
--- a/lldb/include/lldb/Host/Socket.h
+++ b/lldb/include/lldb/Host/Socket.h
@@ -151,6 +151,9 @@ class Socket : public IOObject {
// If this Socket is connected then return the URI used to connect.
virtual std::string GetRemoteConnectionURI() const { return ""; };
+ // If the Socket is listening then return the URI for clients to connect.
+ virtual std::string GetListeningConnectionURI() const { return ""; }
+
protected:
Socket(SocketProtocol protocol, bool should_close);
diff --git a/lldb/include/lldb/Host/common/TCPSocket.h b/lldb/include/lldb/Host/common/TCPSocket.h
index ca36622691fe9a..ab6bf5ab97cae7 100644
--- a/lldb/include/lldb/Host/common/TCPSocket.h
+++ b/lldb/include/lldb/Host/common/TCPSocket.h
@@ -52,6 +52,8 @@ class TCPSocket : public Socket {
std::string GetRemoteConnectionURI() const override;
+ std::string GetListeningConnectionURI() const override;
+
private:
TCPSocket(NativeSocket socket, const TCPSocket &listen_socket);
diff --git a/lldb/include/lldb/Host/posix/DomainSocket.h b/lldb/include/lldb/Host/posix/DomainSocket.h
index d4e0d43ee169c1..d79564cc76dafd 100644
--- a/lldb/include/lldb/Host/posix/DomainSocket.h
+++ b/lldb/include/lldb/Host/posix/DomainSocket.h
@@ -27,6 +27,8 @@ class DomainSocket : public Socket {
std::string GetRemoteConnectionURI() const override;
+ std::string GetListeningConnectionURI() const override;
+
protected:
DomainSocket(SocketProtocol protocol);
diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp
index 5d863954ee8868..b7bd62ff04855e 100644
--- a/lldb/source/Host/common/TCPSocket.cpp
+++ b/lldb/source/Host/common/TCPSocket.cpp
@@ -81,6 +81,12 @@ std::string TCPSocket::GetLocalIPAddress() const {
socklen_t sock_addr_len = sock_addr.GetMaxLength();
if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
return sock_addr.GetIPAddress();
+ } else if (!m_listen_sockets.empty()) {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength();
+ if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
+ &sock_addr_len) == 0)
+ return sock_addr.GetIPAddress();
}
return "";
}
@@ -115,6 +121,15 @@ std::string TCPSocket::GetRemoteConnectionURI() const {
return "";
}
+std::string TCPSocket::GetListeningConnectionURI() const {
+ if (!m_listen_sockets.empty()) {
+ return std::string(llvm::formatv(
+ "connection://[{0}]:{1}", GetLocalIPAddress(), GetLocalPortNumber()));
+ }
+
+ return "";
+}
+
Status TCPSocket::CreateSocket(int domain) {
Status error;
if (IsValid())
@@ -176,8 +191,9 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
if (host_port->hostname == "*")
host_port->hostname = "0.0.0.0";
- std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
- host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
+ std::vector<SocketAddress> addresses =
+ SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr,
+ AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
for (SocketAddress &address : addresses) {
int fd =
Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, error);
@@ -191,7 +207,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
}
SocketAddress listen_address = address;
- if(!listen_address.IsLocalhost())
+ if (!listen_address.IsLocalhost())
listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
else
listen_address.SetPort(host_port->port);
diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp
index 0451834630d33f..beec3c225ecc62 100644
--- a/lldb/source/Host/posix/DomainSocket.cpp
+++ b/lldb/source/Host/posix/DomainSocket.cpp
@@ -86,7 +86,8 @@ Status DomainSocket::Connect(llvm::StringRef name) {
if (error.Fail())
return error;
if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
- (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
+ (struct sockaddr *)&saddr_un,
+ saddr_un_len) < 0)
SetLastError(error);
return error;
@@ -175,3 +176,17 @@ std::string DomainSocket::GetRemoteConnectionURI() const {
"{0}://{1}",
GetNameOffset() == 0 ? "unix-connect" : "unix-abstract-connect", name);
}
+
+std::string DomainSocket::GetListeningConnectionURI() const {
+ if (m_socket == kInvalidSocketValue)
+ return "";
+
+ struct sockaddr_un addr;
+ bzero(&addr, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ socklen_t addr_len = sizeof(struct sockaddr_un);
+ if (::getsockname(m_socket, (struct sockaddr *)&addr, &addr_len) != 0)
+ return "";
+
+ return llvm::formatv("unix-connect://{0}", addr.sun_path);
+}
diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
index b20cfe54640285..b69e8874ca01dc 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -63,9 +63,8 @@ TEST_P(SocketTest, DecodeHostAndPort) {
EXPECT_THAT_EXPECTED(Socket::DecodeHostAndPort("*:65535"),
llvm::HasValue(Socket::HostAndPort{"*", 65535}));
- EXPECT_THAT_EXPECTED(
- Socket::DecodeHostAndPort("[::1]:12345"),
- llvm::HasValue(Socket::HostAndPort{"::1", 12345}));
+ EXPECT_THAT_EXPECTED(Socket::DecodeHostAndPort("[::1]:12345"),
+ llvm::HasValue(Socket::HostAndPort{"::1", 12345}));
EXPECT_THAT_EXPECTED(
Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345"),
@@ -75,7 +74,8 @@ TEST_P(SocketTest, DecodeHostAndPort) {
#if LLDB_ENABLE_POSIX
TEST_P(SocketTest, DomainListenConnectAccept) {
llvm::SmallString<64> Path;
- std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
+ std::error_code EC =
+ llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
ASSERT_FALSE(EC);
llvm::sys::path::append(Path, "test");
@@ -88,6 +88,27 @@ TEST_P(SocketTest, DomainListenConnectAccept) {
CreateDomainConnectedSockets(Path, &socket_a_up, &socket_b_up);
}
+TEST_P(SocketTest, DomainListenGetListeningConnectionURI) {
+ llvm::SmallString<64> Path;
+ std::error_code EC =
+ llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
+ ASSERT_FALSE(EC);
+ llvm::sys::path::append(Path, "test");
+
+ // Skip the test if the $TMPDIR is too long to hold a domain socket.
+ if (Path.size() > 107u)
+ return;
+
+ auto listen_socket_up = std::make_unique<DomainSocket>(
+ /*should_close=*/true);
+ Status error = listen_socket_up->Listen(Path, 5);
+ ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
+ ASSERT_TRUE(listen_socket_up->IsValid());
+
+ ASSERT_EQ(listen_socket_up->GetListeningConnectionURI(),
+ llvm::formatv("unix-connect://{0}", Path).str());
+}
+
TEST_P(SocketTest, DomainMainLoopAccept) {
llvm::SmallString<64> Path;
std::error_code EC =
@@ -225,12 +246,28 @@ TEST_P(SocketTest, TCPListen0GetPort) {
if (!HostSupportsIPv4())
return;
llvm::Expected<std::unique_ptr<TCPSocket>> sock =
- Socket::TcpListen("10.10.12.3:0", false);
+ Socket::TcpListen("10.10.12.3:0", 5);
ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
ASSERT_TRUE(sock.get()->IsValid());
EXPECT_NE(sock.get()->GetLocalPortNumber(), 0);
}
+TEST_P(SocketTest, TCPListen0GetListeningConnectionURI) {
+ std::string addr = llvm::formatv("[{0}]:0", GetParam().localhost_ip).str();
+ llvm::Expected<std::unique_ptr<TCPSocket>> sock = Socket::TcpListen(addr);
+ ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
+ ASSERT_TRUE(sock.get()->IsValid());
+ std::string uri = sock.get()->GetListeningConnectionURI();
+
+ // Ensure the URI is not "".
+ EXPECT_FALSE(uri.empty());
+ EXPECT_NE(uri, addr);
+ EXPECT_EQ(uri,
+ llvm::formatv("connection://[{0}]:{1}", GetParam().localhost_ip,
+ sock->get()->GetLocalPortNumber())
+ .str());
+}
+
TEST_P(SocketTest, TCPGetConnectURI) {
std::unique_ptr<TCPSocket> socket_a_up;
std::unique_ptr<TCPSocket> socket_b_up;
@@ -260,8 +297,8 @@ TEST_P(SocketTest, UDPGetConnectURI) {
#if LLDB_ENABLE_POSIX
TEST_P(SocketTest, DomainGetConnectURI) {
llvm::SmallString<64> domain_path;
- std::error_code EC =
- llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
+ std::error_code EC = llvm::sys::fs::createUniqueDirectory(
+ "DomainListenConnectAccept", domain_path);
ASSERT_FALSE(EC);
llvm::sys::path::append(domain_path, "test");
More information about the lldb-commits
mailing list