Make ConnectionFileDescription work with all sockets
authorAntonio Afonso <antonio.afonso@gmail.com>
Thu, 30 May 2019 23:30:35 +0000 (23:30 +0000)
committerAntonio Afonso <antonio.afonso@gmail.com>
Thu, 30 May 2019 23:30:35 +0000 (23:30 +0000)
Summary:
My main goal here is to make lldb-server work with Android Studio.

This is currently not the case because lldb-server is started in platform mode listening on a domain socket. When Android Studio connects to it lldb-server crashes because even though it's listening on a domain socket as soon as it gets a connection it asserts that it's a TCP connection, which will obviously fails for any non-tcp connection.

To do this I came up with a new method called GetConnectURI() in Socket that returns the URI needed to connect to the connected portion of the socket.

Reviewers: labath, clayborg, xiaobai

Reviewed By: labath

Subscribers: mgorny, jfb, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D62089

llvm-svn: 362173

lldb/include/lldb/Host/Socket.h
lldb/include/lldb/Host/common/TCPSocket.h
lldb/include/lldb/Host/common/UDPSocket.h
lldb/include/lldb/Host/posix/DomainSocket.h
lldb/source/Host/common/TCPSocket.cpp
lldb/source/Host/common/UDPSocket.cpp
lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
lldb/source/Host/posix/DomainSocket.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
lldb/unittests/Host/SocketTest.cpp

index 0981808..6f96bd7 100644 (file)
@@ -102,6 +102,9 @@ public:
                                 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);
index 526c39b..faf3bb6 100644 (file)
@@ -46,6 +46,8 @@ public:
 
   bool IsValid() const override;
 
+  std::string GetRemoteConnectionURI() const override;
+
 private:
   TCPSocket(NativeSocket socket, const TCPSocket &listen_socket);
 
index 8ab6783..b7b6db6 100644 (file)
@@ -19,6 +19,8 @@ public:
   static Status Connect(llvm::StringRef name, bool child_processes_inherit,
                         Socket *&socket);
 
+  std::string GetRemoteConnectionURI() const override;
+
 private:
   UDPSocket(NativeSocket socket);
 
index 87db2db..e407ce1 100644 (file)
@@ -20,11 +20,14 @@ public:
   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);
index f97ca9e..201ddd3 100644 (file)
@@ -118,6 +118,14 @@ std::string TCPSocket::GetRemoteIPAddress() const {
   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())
index e1bcd0c..8dbf57d 100644 (file)
@@ -134,3 +134,11 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
   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 "";
+}
index 237d11a..067e859 100644 (file)
@@ -758,13 +758,7 @@ void ConnectionFileDescriptor::SetChildProcessesInherit(
 }
 
 void ConnectionFileDescriptor::InitializeSocket(Socket *socket) {
-  assert(socket->GetSocketProtocol() == Socket::ProtocolTcp);
-  TCPSocket *tcp_socket = static_cast<TCPSocket *>(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();
 }
index c6366e4..f4b5f42 100644 (file)
@@ -125,3 +125,28 @@ size_t DomainSocket::GetNameOffset() const { return 0; }
 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 "";
+}
index 7157f53..6deb75f 100644 (file)
@@ -115,25 +115,24 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
                 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;
index 26a8bd7..0d1851e 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SocketTestUtilities.h"
+#include "lldb/Utility/UriParser.h"
 #include "gtest/gtest.h"
 
 using namespace lldb_private;
@@ -147,3 +148,64 @@ TEST_F(SocketTest, TCPListen0GetPort) {
   EXPECT_TRUE(socket_up->IsValid());
   EXPECT_NE(socket_up->GetLocalPortNumber(), 0);
 }
+
+TEST_F(SocketTest, TCPGetConnectURI) {
+  std::unique_ptr<TCPSocket> socket_a_up;
+  std::unique_ptr<TCPSocket> 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<DomainSocket> socket_a_up;
+  std::unique_ptr<DomainSocket> 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