[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