|
17 | 17 | #include "lldb/Utility/LLDBLog.h"
|
18 | 18 | #include "lldb/Utility/Log.h"
|
19 | 19 |
|
| 20 | +#include "llvm/ADT/StringExtras.h" |
20 | 21 | #include "llvm/Config/llvm-config.h"
|
21 | 22 | #include "llvm/Support/Errno.h"
|
22 | 23 | #include "llvm/Support/WindowsError.h"
|
@@ -94,6 +95,25 @@ uint16_t TCPSocket::GetLocalPortNumber() const {
|
94 | 95 | return 0;
|
95 | 96 | }
|
96 | 97 |
|
| 98 | +// Return all the port numbers that is being used by the socket. |
| 99 | +std::set<uint16_t> TCPSocket::GetLocalPortNumbers() const { |
| 100 | + std::set<uint16_t> ports; |
| 101 | + if (m_socket != kInvalidSocketValue) { |
| 102 | + SocketAddress sock_addr; |
| 103 | + socklen_t sock_addr_len = sock_addr.GetMaxLength(); |
| 104 | + if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) |
| 105 | + ports.insert(sock_addr.GetPort()); |
| 106 | + } else if (!m_listen_sockets.empty()) { |
| 107 | + SocketAddress sock_addr; |
| 108 | + socklen_t sock_addr_len = sock_addr.GetMaxLength(); |
| 109 | + for (auto listen_socket : m_listen_sockets) { |
| 110 | + if (::getsockname(listen_socket.first, sock_addr, &sock_addr_len) == 0) |
| 111 | + ports.insert(sock_addr.GetPort()); |
| 112 | + } |
| 113 | + } |
| 114 | + return ports; |
| 115 | +} |
| 116 | + |
97 | 117 | std::string TCPSocket::GetLocalIPAddress() const {
|
98 | 118 | // We bound to port zero, so we need to figure out which port we actually
|
99 | 119 | // bound to
|
@@ -196,49 +216,66 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
|
196 | 216 | if (!host_port)
|
197 | 217 | return Status(host_port.takeError());
|
198 | 218 |
|
| 219 | + llvm::SmallVector<uint16_t, 2> ports; |
| 220 | + ports.push_back(host_port->port); |
| 221 | + |
| 222 | + llvm::SmallVector<llvm::StringRef, 2> extra_ports; |
| 223 | + name.split(extra_ports, ',', -1, false); |
| 224 | + if (extra_ports.size() > 1) { |
| 225 | + for (auto i = extra_ports.begin() + 1; i != extra_ports.end(); ++i) { |
| 226 | + uint16_t port; |
| 227 | + if (!llvm::to_integer(*i, port, 10)) |
| 228 | + return Status("invalid extra port number %s", i->str().c_str()); |
| 229 | + ports.push_back(port); |
| 230 | + } |
| 231 | + } |
| 232 | + |
199 | 233 | if (host_port->hostname == "*")
|
200 | 234 | host_port->hostname = "0.0.0.0";
|
201 | 235 | std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
|
202 | 236 | host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
203 | 237 | for (SocketAddress &address : addresses) {
|
204 |
| - int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, |
205 |
| - m_child_processes_inherit, error); |
206 |
| - if (error.Fail() || fd < 0) |
207 |
| - continue; |
208 |
| - |
209 |
| - // enable local address reuse |
210 |
| - int option_value = 1; |
211 |
| - set_socket_option_arg_type option_value_p = |
212 |
| - reinterpret_cast<set_socket_option_arg_type>(&option_value); |
213 |
| - if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, |
214 |
| - sizeof(option_value)) == -1) { |
215 |
| - CLOSE_SOCKET(fd); |
216 |
| - continue; |
217 |
| - } |
218 |
| - |
219 |
| - SocketAddress listen_address = address; |
220 |
| - if(!listen_address.IsLocalhost()) |
221 |
| - listen_address.SetToAnyAddress(address.GetFamily(), host_port->port); |
222 |
| - else |
223 |
| - listen_address.SetPort(host_port->port); |
| 238 | + for (size_t i = 0; i < ports.size(); ++i) { |
| 239 | + int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, |
| 240 | + m_child_processes_inherit, error); |
| 241 | + if (error.Fail() || fd < 0) |
| 242 | + continue; |
| 243 | + |
| 244 | + // enable local address reuse |
| 245 | + int option_value = 1; |
| 246 | + set_socket_option_arg_type option_value_p = |
| 247 | + reinterpret_cast<set_socket_option_arg_type>(&option_value); |
| 248 | + if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, |
| 249 | + sizeof(option_value)) == -1) { |
| 250 | + CLOSE_SOCKET(fd); |
| 251 | + continue; |
| 252 | + } |
224 | 253 |
|
225 |
| - int err = |
226 |
| - ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength()); |
227 |
| - if (err != -1) |
228 |
| - err = ::listen(fd, backlog); |
| 254 | + SocketAddress listen_address = address; |
| 255 | + if (!listen_address.IsLocalhost()) |
| 256 | + listen_address.SetToAnyAddress(address.GetFamily(), ports[i]); |
| 257 | + else |
| 258 | + listen_address.SetPort(ports[i]); |
| 259 | + |
| 260 | + int err = |
| 261 | + ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength()); |
| 262 | + if (err != -1) |
| 263 | + err = ::listen(fd, backlog); |
| 264 | + |
| 265 | + if (err == -1) { |
| 266 | + error = GetLastSocketError(); |
| 267 | + CLOSE_SOCKET(fd); |
| 268 | + continue; |
| 269 | + } |
229 | 270 |
|
230 |
| - if (err == -1) { |
231 |
| - error = GetLastSocketError(); |
232 |
| - CLOSE_SOCKET(fd); |
233 |
| - continue; |
234 |
| - } |
| 271 | + if (ports[i] == 0) { |
| 272 | + socklen_t sa_len = address.GetLength(); |
| 273 | + if (getsockname(fd, &address.sockaddr(), &sa_len) == 0) |
| 274 | + ports[i] = address.GetPort(); |
| 275 | + } |
235 | 276 |
|
236 |
| - if (host_port->port == 0) { |
237 |
| - socklen_t sa_len = address.GetLength(); |
238 |
| - if (getsockname(fd, &address.sockaddr(), &sa_len) == 0) |
239 |
| - host_port->port = address.GetPort(); |
| 277 | + m_listen_sockets[fd] = address; |
240 | 278 | }
|
241 |
| - m_listen_sockets[fd] = address; |
242 | 279 | }
|
243 | 280 |
|
244 | 281 | if (m_listen_sockets.empty()) {
|
|
0 commit comments