[Lldb-commits] [lldb] [lldb] Updated TCPSocket to listen multiple ports on the same single thread (PR #104797)

via lldb-commits lldb-commits at lists.llvm.org
Mon Aug 19 08:14:45 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Dmitry Vasilyev (slydiman)

<details>
<summary>Changes</summary>

This is prerequisite for #<!-- -->104238.

---
Full diff: https://github.com/llvm/llvm-project/pull/104797.diff


3 Files Affected:

- (modified) lldb/include/lldb/Host/common/TCPSocket.h (+3) 
- (modified) lldb/source/Host/common/TCPSocket.cpp (+71-34) 
- (modified) lldb/unittests/Host/SocketTest.cpp (+13) 


``````````diff
diff --git a/lldb/include/lldb/Host/common/TCPSocket.h b/lldb/include/lldb/Host/common/TCPSocket.h
index b782c9e6096c44..b45fdae00c6b43 100644
--- a/lldb/include/lldb/Host/common/TCPSocket.h
+++ b/lldb/include/lldb/Host/common/TCPSocket.h
@@ -24,6 +24,9 @@ class TCPSocket : public Socket {
   // returns port number or 0 if error
   uint16_t GetLocalPortNumber() const;
 
+  // returns port numbers of all listening sockets
+  std::set<uint16_t> GetLocalPortNumbers() const;
+
   // returns ip address string or empty string if error
   std::string GetLocalIPAddress() const;
 
diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp
index df4737216ed3ac..e659b20bb0045e 100644
--- a/lldb/source/Host/common/TCPSocket.cpp
+++ b/lldb/source/Host/common/TCPSocket.cpp
@@ -17,6 +17,7 @@
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
 
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/Errno.h"
 #include "llvm/Support/WindowsError.h"
@@ -94,6 +95,25 @@ uint16_t TCPSocket::GetLocalPortNumber() const {
   return 0;
 }
 
+// Return all the port numbers that is being used by the socket.
+std::set<uint16_t> TCPSocket::GetLocalPortNumbers() const {
+  std::set<uint16_t> ports;
+  if (m_socket != kInvalidSocketValue) {
+    SocketAddress sock_addr;
+    socklen_t sock_addr_len = sock_addr.GetMaxLength();
+    if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
+      ports.insert(sock_addr.GetPort());
+  } else if (!m_listen_sockets.empty()) {
+    SocketAddress sock_addr;
+    socklen_t sock_addr_len = sock_addr.GetMaxLength();
+    for (auto listen_socket : m_listen_sockets) {
+      if (::getsockname(listen_socket.first, sock_addr, &sock_addr_len) == 0)
+        ports.insert(sock_addr.GetPort());
+    }
+  }
+  return ports;
+}
+
 std::string TCPSocket::GetLocalIPAddress() const {
   // We bound to port zero, so we need to figure out which port we actually
   // bound to
@@ -196,49 +216,66 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
   if (!host_port)
     return Status(host_port.takeError());
 
+  llvm::SmallVector<uint16_t, 2> ports;
+  ports.push_back(host_port->port);
+
+  llvm::SmallVector<llvm::StringRef, 2> extra_ports;
+  name.split(extra_ports, ',', -1, false);
+  if (extra_ports.size() > 1) {
+    for (auto i = extra_ports.begin() + 1; i != extra_ports.end(); ++i) {
+      uint16_t port;
+      if (!llvm::to_integer(*i, port, 10))
+        return Status("invalid extra port number %s", i->str().c_str());
+      ports.push_back(port);
+    }
+  }
+
   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);
   for (SocketAddress &address : addresses) {
-    int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
-                                  m_child_processes_inherit, error);
-    if (error.Fail() || fd < 0)
-      continue;
-
-    // enable local address reuse
-    int option_value = 1;
-    set_socket_option_arg_type option_value_p =
-        reinterpret_cast<set_socket_option_arg_type>(&option_value);
-    if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
-                     sizeof(option_value)) == -1) {
-      CLOSE_SOCKET(fd);
-      continue;
-    }
-
-    SocketAddress listen_address = address;
-    if(!listen_address.IsLocalhost())
-      listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
-    else
-      listen_address.SetPort(host_port->port);
+    for (size_t i = 0; i < ports.size(); ++i) {
+      int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
+                                    m_child_processes_inherit, error);
+      if (error.Fail() || fd < 0)
+        continue;
+
+      // enable local address reuse
+      int option_value = 1;
+      set_socket_option_arg_type option_value_p =
+          reinterpret_cast<set_socket_option_arg_type>(&option_value);
+      if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
+                       sizeof(option_value)) == -1) {
+        CLOSE_SOCKET(fd);
+        continue;
+      }
 
-    int err =
-        ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
-    if (err != -1)
-      err = ::listen(fd, backlog);
+      SocketAddress listen_address = address;
+      if (!listen_address.IsLocalhost())
+        listen_address.SetToAnyAddress(address.GetFamily(), ports[i]);
+      else
+        listen_address.SetPort(ports[i]);
+
+      int err =
+          ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
+      if (err != -1)
+        err = ::listen(fd, backlog);
+
+      if (err == -1) {
+        error = GetLastSocketError();
+        CLOSE_SOCKET(fd);
+        continue;
+      }
 
-    if (err == -1) {
-      error = GetLastSocketError();
-      CLOSE_SOCKET(fd);
-      continue;
-    }
+      if (ports[i] == 0) {
+        socklen_t sa_len = address.GetLength();
+        if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
+          ports[i] = address.GetPort();
+      }
 
-    if (host_port->port == 0) {
-      socklen_t sa_len = address.GetLength();
-      if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
-        host_port->port = address.GetPort();
+      m_listen_sockets[fd] = address;
     }
-    m_listen_sockets[fd] = address;
   }
 
   if (m_listen_sockets.empty()) {
diff --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
index 78e1e11df06562..3e87af57d3ce51 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -136,6 +136,19 @@ TEST_P(SocketTest, TCPListen0GetPort) {
   EXPECT_NE(sock.get()->GetLocalPortNumber(), 0);
 }
 
+TEST_P(SocketTest, TCPListen00GetPort) {
+  if (!HostSupportsIPv4())
+    return;
+  llvm::Expected<std::unique_ptr<TCPSocket>> sock =
+      Socket::TcpListen("10.10.12.3:0,0", false);
+  ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
+  ASSERT_TRUE(sock.get()->IsValid());
+  std::set<uint16_t> ports = sock.get()->GetLocalPortNumbers();
+  ASSERT_EQ(2, ports.size());
+  EXPECT_NE(*ports.begin(), 0);
+  EXPECT_NE(*std::next(ports.begin()), 0);
+}
+
 TEST_P(SocketTest, TCPGetConnectURI) {
   std::unique_ptr<TCPSocket> socket_a_up;
   std::unique_ptr<TCPSocket> socket_b_up;

``````````

</details>


https://github.com/llvm/llvm-project/pull/104797


More information about the lldb-commits mailing list