diff --git a/lldb/include/lldb/Host/Socket.h b/lldb/include/lldb/Host/Socket.h --- a/lldb/include/lldb/Host/Socket.h +++ b/lldb/include/lldb/Host/Socket.h @@ -102,6 +102,9 @@ std::string &host_str, std::string &port_str, int32_t &port, Status *error_ptr); + // If this Socket is connected then return the URI used to connect. + virtual std::string GetRemoteConnectionURI() const { return ""; }; + protected: Socket(SocketProtocol protocol, bool should_close, bool m_child_process_inherit); diff --git a/lldb/include/lldb/Host/common/TCPSocket.h b/lldb/include/lldb/Host/common/TCPSocket.h --- a/lldb/include/lldb/Host/common/TCPSocket.h +++ b/lldb/include/lldb/Host/common/TCPSocket.h @@ -46,6 +46,8 @@ bool IsValid() const override; + std::string GetRemoteConnectionURI() const override; + private: TCPSocket(NativeSocket socket, const TCPSocket &listen_socket); diff --git a/lldb/include/lldb/Host/common/UDPSocket.h b/lldb/include/lldb/Host/common/UDPSocket.h --- a/lldb/include/lldb/Host/common/UDPSocket.h +++ b/lldb/include/lldb/Host/common/UDPSocket.h @@ -19,6 +19,8 @@ static Status Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket); + std::string GetRemoteConnectionURI() const override; + private: UDPSocket(NativeSocket socket); diff --git a/lldb/include/lldb/Host/posix/DomainSocket.h b/lldb/include/lldb/Host/posix/DomainSocket.h --- a/lldb/include/lldb/Host/posix/DomainSocket.h +++ b/lldb/include/lldb/Host/posix/DomainSocket.h @@ -20,11 +20,14 @@ Status Listen(llvm::StringRef name, int backlog) override; Status Accept(Socket *&socket) override; + std::string GetRemoteConnectionURI() const override; + protected: DomainSocket(SocketProtocol protocol, bool child_processes_inherit); virtual size_t GetNameOffset() const; virtual void DeleteSocketFile(llvm::StringRef name); + std::string GetSocketName() const; private: DomainSocket(NativeSocket socket, const DomainSocket &listen_socket); diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -118,6 +118,14 @@ return ""; } +std::string TCPSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("connect://[{0}]:{1}", GetRemoteIPAddress(), + GetRemotePortNumber()); + } + return ""; +}; + Status TCPSocket::CreateSocket(int domain) { Status error; if (IsValid()) diff --git a/lldb/source/Host/common/UDPSocket.cpp b/lldb/source/Host/common/UDPSocket.cpp --- a/lldb/source/Host/common/UDPSocket.cpp +++ b/lldb/source/Host/common/UDPSocket.cpp @@ -134,3 +134,11 @@ error.Clear(); return error; } + +std::string UDPSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("udp://[{0}]:{1}", m_sockaddr.GetIPAddress(), + m_sockaddr.GetPort()); + } + return ""; +} diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -758,13 +758,7 @@ } void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { - assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); - TCPSocket *tcp_socket = static_cast(socket); - m_write_sp.reset(socket); m_read_sp = m_write_sp; - StreamString strm; - strm.Printf("connect://[%s]:%u", tcp_socket->GetRemoteIPAddress().c_str(), - tcp_socket->GetRemotePortNumber()); - m_uri = strm.GetString(); + m_uri = socket->GetRemoteConnectionURI(); } diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -125,3 +125,28 @@ void DomainSocket::DeleteSocketFile(llvm::StringRef name) { llvm::sys::fs::remove(name); } + +std::string DomainSocket::GetSocketName() const { + if (m_socket != kInvalidSocketValue) { + struct sockaddr_un saddr_un; + saddr_un.sun_family = AF_UNIX; + socklen_t sock_addr_len = sizeof(struct sockaddr_un); + if (::getpeername(m_socket, (struct sockaddr *)&saddr_un, &sock_addr_len) == + 0) + return std::string(saddr_un.sun_path + GetNameOffset(), + sock_addr_len - + offsetof(struct sockaddr_un, sun_path) - + GetNameOffset()); + } + return ""; +} + +std::string DomainSocket::GetRemoteConnectionURI() const { + if (m_socket != kInvalidSocketValue) { + return llvm::formatv("{0}://{1}", + GetNameOffset() == 0 ? "unix-connect" + : "unix-abstract-connect", + GetSocketName()); + } + return ""; +} diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -115,25 +115,24 @@ this, std::placeholders::_1), false); - llvm::StringRef platform_scheme; - llvm::StringRef platform_ip; - int platform_port; - llvm::StringRef platform_path; - std::string platform_uri = GetConnection()->GetURI(); - bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, - platform_port, platform_path); - UNUSED_IF_ASSERT_DISABLED(ok); - assert(ok); - std::ostringstream url; // debugserver does not accept the URL scheme prefix. #if !defined(__APPLE__) url << m_socket_scheme << "://"; #endif uint16_t *port_ptr = &port; - if (m_socket_protocol == Socket::ProtocolTcp) + if (m_socket_protocol == Socket::ProtocolTcp) { + llvm::StringRef platform_scheme; + llvm::StringRef platform_ip; + int platform_port; + llvm::StringRef platform_path; + std::string platform_uri = GetConnection()->GetURI(); + bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, + platform_port, platform_path); + UNUSED_IF_ASSERT_DISABLED(ok); + assert(ok); url << platform_ip.str() << ":" << port; - else { + } else { socket_name = GetDomainSocketPath("gdbserver").GetPath(); url << socket_name; port_ptr = nullptr; diff --git a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp --- a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp +++ b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp @@ -38,8 +38,8 @@ llvm::StringRef hostname; int port; llvm::StringRef path; - EXPECT_TRUE(UriParser::Parse(connection_file_descriptor.GetURI(), scheme, - hostname, port, path)); + std::string uri(connection_file_descriptor.GetURI()); + EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path)); EXPECT_EQ(ip, hostname); EXPECT_EQ(socket->GetRemotePortNumber(), port); } diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp --- a/lldb/unittests/Host/SocketTest.cpp +++ b/lldb/unittests/Host/SocketTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "SocketTestUtilities.h" +#include "lldb/Utility/UriParser.h" #include "gtest/gtest.h" using namespace lldb_private; @@ -147,3 +148,64 @@ EXPECT_TRUE(socket_up->IsValid()); EXPECT_NE(socket_up->GetLocalPortNumber(), 0); } + +TEST_F(SocketTest, TCPGetConnectURI) { + std::unique_ptr socket_a_up; + std::unique_ptr socket_b_up; + if (!IsAddressFamilySupported("127.0.0.1")) { + GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support."; + return; + } + CreateTCPConnectedSockets("127.0.0.1", &socket_a_up, &socket_b_up); + + llvm::StringRef scheme; + llvm::StringRef hostname; + int port; + llvm::StringRef path; + std::string uri(socket_a_up->GetRemoteConnectionURI()); + EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path)); + EXPECT_EQ(scheme, "connect"); + EXPECT_EQ(port, socket_a_up->GetRemotePortNumber()); +} + +TEST_F(SocketTest, UDPGetConnectURI) { + if (!IsAddressFamilySupported("127.0.0.1")) { + GTEST_LOG_(WARNING) << "Skipping test due to missing IPv4 support."; + return; + } + Socket *socket; + bool child_processes_inherit = false; + auto error = + UDPSocket::Connect("127.0.0.1:0", child_processes_inherit, socket); + + llvm::StringRef scheme; + llvm::StringRef hostname; + int port; + llvm::StringRef path; + std::string uri(socket->GetRemoteConnectionURI()); + EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path)); + EXPECT_EQ(scheme, "udp"); +} + +#ifndef LLDB_DISABLE_POSIX +TEST_F(SocketTest, DomainGetConnectURI) { + llvm::SmallString<64> domain_path; + std::error_code EC = + llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path); + ASSERT_FALSE(EC); + llvm::sys::path::append(domain_path, "test"); + + std::unique_ptr socket_a_up; + std::unique_ptr socket_b_up; + CreateDomainConnectedSockets(domain_path, &socket_a_up, &socket_b_up); + + llvm::StringRef scheme; + llvm::StringRef hostname; + int port; + llvm::StringRef path; + std::string uri(socket_a_up->GetRemoteConnectionURI()); + EXPECT_TRUE(UriParser::Parse(uri, scheme, hostname, port, path)); + EXPECT_EQ(scheme, "unix-connect"); + EXPECT_EQ(path, domain_path); +} +#endif \ No newline at end of file