LLDB  mainline
TCPSocket.cpp
Go to the documentation of this file.
1 //===-- TCPSocket.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #if defined(_MSC_VER)
10 #define _WINSOCK_DEPRECATED_NO_WARNINGS
11 #endif
12 
14 
15 #include "lldb/Host/Config.h"
16 #include "lldb/Host/MainLoop.h"
17 #include "lldb/Utility/LLDBLog.h"
18 #include "lldb/Utility/Log.h"
19 
20 #include "llvm/Config/llvm-config.h"
21 #include "llvm/Support/Errno.h"
22 #include "llvm/Support/WindowsError.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 #if LLDB_ENABLE_POSIX
26 #include <arpa/inet.h>
27 #include <netinet/tcp.h>
28 #include <sys/socket.h>
29 #endif
30 
31 #if defined(_WIN32)
32 #include <winsock2.h>
33 #endif
34 
35 #ifdef _WIN32
36 #define CLOSE_SOCKET closesocket
37 typedef const char *set_socket_option_arg_type;
38 #else
39 #include <unistd.h>
40 #define CLOSE_SOCKET ::close
41 typedef const void *set_socket_option_arg_type;
42 #endif
43 
44 using namespace lldb;
45 using namespace lldb_private;
46 
48  std::error_code EC;
49 #ifdef _WIN32
50  EC = llvm::mapWindowsError(WSAGetLastError());
51 #else
52  EC = std::error_code(errno, std::generic_category());
53 #endif
54  return EC;
55 }
56 
57 static const int kType = SOCK_STREAM;
58 
59 TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
60  : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
61 
62 TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
63  : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
64  listen_socket.m_child_processes_inherit) {
65  m_socket = socket;
66 }
67 
68 TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
69  bool child_processes_inherit)
70  : Socket(ProtocolTcp, should_close, child_processes_inherit) {
71  m_socket = socket;
72 }
73 
75 
76 bool TCPSocket::IsValid() const {
77  return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
78 }
79 
80 // Return the port number that is being used by the socket.
83  SocketAddress sock_addr;
84  socklen_t sock_addr_len = sock_addr.GetMaxLength();
85  if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
86  return sock_addr.GetPort();
87  } else if (!m_listen_sockets.empty()) {
88  SocketAddress sock_addr;
89  socklen_t sock_addr_len = sock_addr.GetMaxLength();
90  if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
91  &sock_addr_len) == 0)
92  return sock_addr.GetPort();
93  }
94  return 0;
95 }
96 
98  // We bound to port zero, so we need to figure out which port we actually
99  // bound to
100  if (m_socket != kInvalidSocketValue) {
101  SocketAddress sock_addr;
102  socklen_t sock_addr_len = sock_addr.GetMaxLength();
103  if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
104  return sock_addr.GetIPAddress();
105  }
106  return "";
107 }
108 
110  if (m_socket != kInvalidSocketValue) {
111  SocketAddress sock_addr;
112  socklen_t sock_addr_len = sock_addr.GetMaxLength();
113  if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
114  return sock_addr.GetPort();
115  }
116  return 0;
117 }
118 
120  // We bound to port zero, so we need to figure out which port we actually
121  // bound to
122  if (m_socket != kInvalidSocketValue) {
123  SocketAddress sock_addr;
124  socklen_t sock_addr_len = sock_addr.GetMaxLength();
125  if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
126  return sock_addr.GetIPAddress();
127  }
128  return "";
129 }
130 
132  if (m_socket != kInvalidSocketValue) {
133  return std::string(llvm::formatv(
134  "connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
135  }
136  return "";
137 }
138 
140  Status error;
141  if (IsValid())
142  error = Close();
143  if (error.Fail())
144  return error;
145  m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
147  return error;
148 }
149 
150 Status TCPSocket::Connect(llvm::StringRef name) {
151 
153  LLDB_LOGF(log, "TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
154 
155  Status error;
156  llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
157  if (!host_port)
158  return Status(host_port.takeError());
159 
160  std::vector<SocketAddress> addresses =
161  SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr,
162  AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
163  for (SocketAddress &address : addresses) {
164  error = CreateSocket(address.GetFamily());
165  if (error.Fail())
166  continue;
167 
168  address.SetPort(host_port->port);
169 
170  if (-1 == llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
171  &address.sockaddr(),
172  address.GetLength())) {
173  Close();
174  continue;
175  }
176 
178 
179  error.Clear();
180  return error;
181  }
182 
183  error.SetErrorString("Failed to connect port");
184  return error;
185 }
186 
187 Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
189  LLDB_LOGF(log, "TCPSocket::%s (%s)", __FUNCTION__, name.data());
190 
191  Status error;
192  llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
193  if (!host_port)
194  return Status(host_port.takeError());
195 
196  if (host_port->hostname == "*")
197  host_port->hostname = "0.0.0.0";
198  std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
199  host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
200  for (SocketAddress &address : addresses) {
201  int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
203  if (error.Fail())
204  continue;
205 
206  // enable local address reuse
207  int option_value = 1;
208  set_socket_option_arg_type option_value_p =
209  reinterpret_cast<set_socket_option_arg_type>(&option_value);
210  ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
211  sizeof(option_value));
212 
213  SocketAddress listen_address = address;
214  if(!listen_address.IsLocalhost())
215  listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
216  else
217  listen_address.SetPort(host_port->port);
218 
219  int err =
220  ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
221  if (-1 != err)
222  err = ::listen(fd, backlog);
223 
224  if (-1 == err) {
226  CLOSE_SOCKET(fd);
227  continue;
228  }
229 
230  if (host_port->port == 0) {
231  socklen_t sa_len = address.GetLength();
232  if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
233  host_port->port = address.GetPort();
234  }
235  m_listen_sockets[fd] = address;
236  }
237 
238  if (m_listen_sockets.empty()) {
239  assert(error.Fail());
240  return error;
241  }
242  return Status();
243 }
244 
246  for (auto socket : m_listen_sockets)
247  CLOSE_SOCKET(socket.first);
248  m_listen_sockets.clear();
249 }
250 
252  Status error;
253  if (m_listen_sockets.size() == 0) {
254  error.SetErrorString("No open listening sockets!");
255  return error;
256  }
257 
258  int sock = -1;
259  int listen_sock = -1;
260  lldb_private::SocketAddress AcceptAddr;
261  MainLoop accept_loop;
262  std::vector<MainLoopBase::ReadHandleUP> handles;
263  for (auto socket : m_listen_sockets) {
264  auto fd = socket.first;
265  auto inherit = this->m_child_processes_inherit;
266  auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
267  handles.emplace_back(accept_loop.RegisterReadObject(
268  io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
269  &listen_sock](MainLoopBase &loop) {
270  socklen_t sa_len = AcceptAddr.GetMaxLength();
271  sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
272  error);
273  listen_sock = fd;
274  loop.RequestTermination();
275  }, error));
276  if (error.Fail())
277  return error;
278  }
279 
280  bool accept_connection = false;
281  std::unique_ptr<TCPSocket> accepted_socket;
282  // Loop until we are happy with our connection
283  while (!accept_connection) {
284  accept_loop.Run();
285 
286  if (error.Fail())
287  return error;
288 
289  lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
290  if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
291  CLOSE_SOCKET(sock);
292  llvm::errs() << llvm::formatv(
293  "error: rejecting incoming connection from {0} (expecting {1})",
294  AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
295  continue;
296  }
297  accept_connection = true;
298  accepted_socket.reset(new TCPSocket(sock, *this));
299  }
300 
301  if (!accepted_socket)
302  return error;
303 
304  // Keep our TCP packets coming without any delays.
305  accepted_socket->SetOptionNoDelay();
306  error.Clear();
307  conn_socket = accepted_socket.release();
308  return error;
309 }
310 
312  return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
313 }
314 
316  return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
317 }
lldb_private::Socket::kInvalidSocketValue
static const NativeSocket kInvalidSocketValue
Definition: Socket.h:59
lldb_private::SocketAddress::GetIPAddress
std::string GetIPAddress() const
Definition: SocketAddress.cpp:136
lldb_private::TCPSocket::Connect
Status Connect(llvm::StringRef name) override
Definition: TCPSocket.cpp:150
lldb_private::TCPSocket::CloseListenSockets
void CloseListenSockets()
Definition: TCPSocket.cpp:245
lldb_private::MainLoop::RegisterReadObject
ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, Status &error) override
Definition: MainLoop.cpp:272
lldb_private::Socket::m_child_processes_inherit
bool m_child_processes_inherit
Definition: Socket.h:124
lldb_private::TCPSocket::Accept
Status Accept(Socket *&conn_socket) override
Definition: TCPSocket.cpp:251
lldb_private::SocketAddress::GetPort
uint16_t GetPort() const
Definition: SocketAddress.cpp:153
kType
static const int kType
Definition: TCPSocket.cpp:57
CLOSE_SOCKET
#define CLOSE_SOCKET
Definition: TCPSocket.cpp:40
lldb_private::Socket
Definition: Socket.h:41
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:343
lldb_private::SocketAddress::IsLocalhost
bool IsLocalhost() const
Definition: SocketAddress.cpp:297
lldb_private::TCPSocket::m_listen_sockets
std::map< int, SocketAddress > m_listen_sockets
Definition: TCPSocket.h:56
lldb_private::SocketAddress::SetToAnyAddress
bool SetToAnyAddress(sa_family_t family, uint16_t port)
Definition: SocketAddress.cpp:269
lldb_private::TCPSocket::IsValid
bool IsValid() const override
Definition: TCPSocket.cpp:76
lldb_private::MainLoop::Run
Status Run() override
Definition: MainLoop.cpp:394
lldb_private::TCPSocket::SetOptionReuseAddress
int SetOptionReuseAddress()
Definition: TCPSocket.cpp:315
lldb_private::TCPSocket::TCPSocket
TCPSocket(bool should_close, bool child_processes_inherit)
Definition: TCPSocket.cpp:59
lldb_private::Socket::SetOption
int SetOption(int level, int option_name, int option_value)
lldb_private::MainLoopBase
Definition: MainLoopBase.h:31
lldb_private::SocketAddress::SetPort
bool SetPort(uint16_t port)
Definition: SocketAddress.cpp:163
lldb_private::Socket::Close
Status Close() override
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::LLDBLog::Connection
@ Connection
Log.h
lldb_private::Socket::m_socket
NativeSocket m_socket
Definition: Socket.h:123
lldb_private::TCPSocket::GetLocalIPAddress
std::string GetLocalIPAddress() const
Definition: TCPSocket.cpp:97
lldb_private::TCPSocket::GetRemoteIPAddress
std::string GetRemoteIPAddress() const
Definition: TCPSocket.cpp:119
lldb_private::Socket::GetNativeSocket
NativeSocket GetNativeSocket() const
Definition: Socket.h:90
lldb_private::SocketAddress::sockaddr
struct sockaddr & sockaddr()
Definition: SocketAddress.h:119
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::SocketAddress::GetLength
socklen_t GetLength() const
Definition: SocketAddress.cpp:115
lldb_private::NativeSocket
int NativeSocket
Definition: Socket.h:36
lldb_private::SocketAddress::IsAnyAddr
bool IsAnyAddr() const
Definition: SocketAddress.cpp:291
GetLastSocketError
static Status GetLastSocketError()
Definition: TCPSocket.cpp:47
lldb_private::LLDBLog::Communication
@ Communication
lldb_private::Status
Definition: Status.h:44
lldb_private::Socket::DecodeHostAndPort
static llvm::Expected< HostAndPort > DecodeHostAndPort(llvm::StringRef host_and_port)
Definition: Socket.cpp:188
lldb_private::SocketAddress::GetMaxLength
static socklen_t GetMaxLength()
Definition: SocketAddress.cpp:123
lldb_private::TCPSocket::SetOptionNoDelay
int SetOptionNoDelay()
Definition: TCPSocket.cpp:311
lldb_private::Socket::CreateSocket
static NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit, Status &error)
lldb_private::MainLoop
Definition: MainLoop.h:39
uint16_t
TCPSocket.h
lldb_private::TCPSocket
Definition: TCPSocket.h:17
lldb_private::TCPSocket::GetRemoteConnectionURI
std::string GetRemoteConnectionURI() const override
Definition: TCPSocket.cpp:131
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
set_socket_option_arg_type
const typedef void * set_socket_option_arg_type
Definition: TCPSocket.cpp:41
lldb_private::Log
Definition: Log.h:115
lldb_private::TCPSocket::CreateSocket
Status CreateSocket(int domain)
Definition: TCPSocket.cpp:139
lldb_private::TCPSocket::GetRemotePortNumber
uint16_t GetRemotePortNumber() const
Definition: TCPSocket.cpp:109
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
lldb_private::TCPSocket::GetLocalPortNumber
uint16_t GetLocalPortNumber() const
Definition: TCPSocket.cpp:81
lldb_private::SocketAddress
Definition: SocketAddress.h:34
lldb_private::TCPSocket::~TCPSocket
~TCPSocket() override
Definition: TCPSocket.cpp:74
lldb
Definition: SBAddress.h:15
MainLoop.h
lldb_private::SocketAddress::GetAddressInfo
static std::vector< SocketAddress > GetAddressInfo(const char *hostname, const char *servname, int ai_family, int ai_socktype, int ai_protocol, int ai_flags=0)
Definition: SocketAddress.cpp:221
LLDBLog.h
lldb_private::TCPSocket::Listen
Status Listen(llvm::StringRef name, int backlog) override
Definition: TCPSocket.cpp:187