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/Log.h"
18 
19 #include "llvm/Config/llvm-config.h"
20 #include "llvm/Support/Errno.h"
21 #include "llvm/Support/WindowsError.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 #if LLDB_ENABLE_POSIX
25 #include <arpa/inet.h>
26 #include <netinet/tcp.h>
27 #include <sys/socket.h>
28 #endif
29 
30 #if defined(_WIN32)
31 #include <winsock2.h>
32 #endif
33 
34 #ifdef _WIN32
35 #define CLOSE_SOCKET closesocket
36 typedef const char *set_socket_option_arg_type;
37 #else
38 #include <unistd.h>
39 #define CLOSE_SOCKET ::close
40 typedef const void *set_socket_option_arg_type;
41 #endif
42 
43 using namespace lldb;
44 using namespace lldb_private;
45 
47  std::error_code EC;
48 #ifdef _WIN32
49  EC = llvm::mapWindowsError(WSAGetLastError());
50 #else
51  EC = std::error_code(errno, std::generic_category());
52 #endif
53  return EC;
54 }
55 
56 static const int kType = SOCK_STREAM;
57 
58 TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
59  : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
60 
61 TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
62  : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
63  listen_socket.m_child_processes_inherit) {
64  m_socket = socket;
65 }
66 
67 TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
68  bool child_processes_inherit)
69  : Socket(ProtocolTcp, should_close, child_processes_inherit) {
70  m_socket = socket;
71 }
72 
74 
75 bool TCPSocket::IsValid() const {
76  return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
77 }
78 
79 // Return the port number that is being used by the socket.
82  SocketAddress sock_addr;
83  socklen_t sock_addr_len = sock_addr.GetMaxLength();
84  if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
85  return sock_addr.GetPort();
86  } else if (!m_listen_sockets.empty()) {
87  SocketAddress sock_addr;
88  socklen_t sock_addr_len = sock_addr.GetMaxLength();
89  if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
90  &sock_addr_len) == 0)
91  return sock_addr.GetPort();
92  }
93  return 0;
94 }
95 
97  // We bound to port zero, so we need to figure out which port we actually
98  // bound to
100  SocketAddress sock_addr;
101  socklen_t sock_addr_len = sock_addr.GetMaxLength();
102  if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
103  return sock_addr.GetIPAddress();
104  }
105  return "";
106 }
107 
109  if (m_socket != kInvalidSocketValue) {
110  SocketAddress sock_addr;
111  socklen_t sock_addr_len = sock_addr.GetMaxLength();
112  if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
113  return sock_addr.GetPort();
114  }
115  return 0;
116 }
117 
119  // We bound to port zero, so we need to figure out which port we actually
120  // bound to
121  if (m_socket != kInvalidSocketValue) {
122  SocketAddress sock_addr;
123  socklen_t sock_addr_len = sock_addr.GetMaxLength();
124  if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
125  return sock_addr.GetIPAddress();
126  }
127  return "";
128 }
129 
131  if (m_socket != kInvalidSocketValue) {
132  return std::string(llvm::formatv(
133  "connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
134  }
135  return "";
136 }
137 
139  Status error;
140  if (IsValid())
141  error = Close();
142  if (error.Fail())
143  return error;
144  m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
146  return error;
147 }
148 
149 Status TCPSocket::Connect(llvm::StringRef name) {
150 
152  LLDB_LOGF(log, "TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
153 
154  Status error;
155  std::string host_str;
156  std::string port_str;
157  uint16_t port;
158  if (llvm::Error decode_error =
159  DecodeHostAndPort(name, host_str, port_str, port))
160  return Status(std::move(decode_error));
161 
162  std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
163  host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
164  for (SocketAddress &address : addresses) {
165  error = CreateSocket(address.GetFamily());
166  if (error.Fail())
167  continue;
168 
169  address.SetPort(port);
170 
171  if (-1 == llvm::sys::RetryAfterSignal(-1, ::connect,
172  GetNativeSocket(), &address.sockaddr(), address.GetLength())) {
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  std::string host_str;
193  std::string port_str;
194  uint16_t port;
195  if (llvm::Error decode_error =
196  DecodeHostAndPort(name, host_str, port_str, port))
197  return Status(std::move(decode_error));
198 
199  if (host_str == "*")
200  host_str = "0.0.0.0";
201  std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
202  host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
203  for (SocketAddress &address : addresses) {
204  int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
206  if (error.Fail())
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  ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
214  sizeof(option_value));
215 
216  SocketAddress listen_address = address;
217  if(!listen_address.IsLocalhost())
218  listen_address.SetToAnyAddress(address.GetFamily(), port);
219  else
220  listen_address.SetPort(port);
221 
222  int err =
223  ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
224  if (-1 != err)
225  err = ::listen(fd, backlog);
226 
227  if (-1 == err) {
229  CLOSE_SOCKET(fd);
230  continue;
231  }
232 
233  if (port == 0) {
234  socklen_t sa_len = address.GetLength();
235  if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
236  port = address.GetPort();
237  }
238  m_listen_sockets[fd] = address;
239  }
240 
241  if (m_listen_sockets.empty()) {
242  assert(error.Fail());
243  return error;
244  }
245  return Status();
246 }
247 
249  for (auto socket : m_listen_sockets)
250  CLOSE_SOCKET(socket.first);
251  m_listen_sockets.clear();
252 }
253 
255  Status error;
256  if (m_listen_sockets.size() == 0) {
257  error.SetErrorString("No open listening sockets!");
258  return error;
259  }
260 
261  int sock = -1;
262  int listen_sock = -1;
263  lldb_private::SocketAddress AcceptAddr;
264  MainLoop accept_loop;
265  std::vector<MainLoopBase::ReadHandleUP> handles;
266  for (auto socket : m_listen_sockets) {
267  auto fd = socket.first;
268  auto inherit = this->m_child_processes_inherit;
269  auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
270  handles.emplace_back(accept_loop.RegisterReadObject(
271  io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
272  &listen_sock](MainLoopBase &loop) {
273  socklen_t sa_len = AcceptAddr.GetMaxLength();
274  sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
275  error);
276  listen_sock = fd;
277  loop.RequestTermination();
278  }, error));
279  if (error.Fail())
280  return error;
281  }
282 
283  bool accept_connection = false;
284  std::unique_ptr<TCPSocket> accepted_socket;
285  // Loop until we are happy with our connection
286  while (!accept_connection) {
287  accept_loop.Run();
288 
289  if (error.Fail())
290  return error;
291 
292  lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
293  if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
294  CLOSE_SOCKET(sock);
295  llvm::errs() << llvm::formatv(
296  "error: rejecting incoming connection from {0} (expecting {1})",
297  AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
298  continue;
299  }
300  accept_connection = true;
301  accepted_socket.reset(new TCPSocket(sock, *this));
302  }
303 
304  if (!accepted_socket)
305  return error;
306 
307  // Keep our TCP packets coming without any delays.
308  accepted_socket->SetOptionNoDelay();
309  error.Clear();
310  conn_socket = accepted_socket.release();
311  return error;
312 }
313 
315  return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
316 }
317 
319  return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
320 }
lldb_private::Socket::kInvalidSocketValue
static const NativeSocket kInvalidSocketValue
Definition: Socket.h:51
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:149
lldb_private::TCPSocket::CloseListenSockets
void CloseListenSockets()
Definition: TCPSocket.cpp:248
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:129
lldb_private::TCPSocket::Accept
Status Accept(Socket *&conn_socket) override
Definition: TCPSocket.cpp:254
lldb_private::SocketAddress::GetPort
uint16_t GetPort() const
Definition: SocketAddress.cpp:153
kType
static const int kType
Definition: TCPSocket.cpp:56
CLOSE_SOCKET
#define CLOSE_SOCKET
Definition: TCPSocket.cpp:39
lldb_private::Socket
Definition: Socket.h:42
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:249
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:75
lldb_private::MainLoop::Run
Status Run() override
Definition: MainLoop.cpp:390
lldb_private::TCPSocket::SetOptionReuseAddress
int SetOptionReuseAddress()
Definition: TCPSocket.cpp:318
lldb_private::TCPSocket::TCPSocket
TCPSocket(bool should_close, bool child_processes_inherit)
Definition: TCPSocket.cpp:58
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
LIBLLDB_LOG_COMMUNICATION
#define LIBLLDB_LOG_COMMUNICATION
Definition: Logging.h:26
Log.h
lldb_private::Socket::m_socket
NativeSocket m_socket
Definition: Socket.h:128
lldb_private::Socket::DecodeHostAndPort
static llvm::Error DecodeHostAndPort(llvm::StringRef host_and_port, std::string &host_str, std::string &port_str, uint16_t &port)
Definition: Socket.cpp:270
lldb_private::TCPSocket::GetLocalIPAddress
std::string GetLocalIPAddress() const
Definition: TCPSocket.cpp:96
lldb_private::TCPSocket::GetRemoteIPAddress
std::string GetRemoteIPAddress() const
Definition: TCPSocket.cpp:118
lldb_private::Socket::GetNativeSocket
NativeSocket GetNativeSocket() const
Definition: Socket.h:94
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:37
lldb_private::SocketAddress::IsAnyAddr
bool IsAnyAddr() const
Definition: SocketAddress.cpp:291
GetLastSocketError
static Status GetLastSocketError()
Definition: TCPSocket.cpp:46
lldb_private::Status
Definition: Status.h:44
lldb_private::SocketAddress::GetMaxLength
static socklen_t GetMaxLength()
Definition: SocketAddress.cpp:123
lldb_private::TCPSocket::SetOptionNoDelay
int SetOptionNoDelay()
Definition: TCPSocket.cpp:314
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:38
uint16_t
LIBLLDB_LOG_CONNECTION
#define LIBLLDB_LOG_CONNECTION
Definition: Logging.h:27
TCPSocket.h
lldb_private::TCPSocket
Definition: TCPSocket.h:17
lldb_private::TCPSocket::GetRemoteConnectionURI
std::string GetRemoteConnectionURI() const override
Definition: TCPSocket.cpp:130
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
set_socket_option_arg_type
const typedef void * set_socket_option_arg_type
Definition: TCPSocket.cpp:40
lldb_private::Log
Definition: Log.h:49
lldb_private::GetLogIfAnyCategoriesSet
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:62
lldb_private::TCPSocket::CreateSocket
Status CreateSocket(int domain)
Definition: TCPSocket.cpp:138
lldb_private::TCPSocket::GetRemotePortNumber
uint16_t GetRemotePortNumber() const
Definition: TCPSocket.cpp:108
lldb_private::TCPSocket::GetLocalPortNumber
uint16_t GetLocalPortNumber() const
Definition: TCPSocket.cpp:80
lldb_private::SocketAddress
Definition: SocketAddress.h:34
lldb_private::TCPSocket::~TCPSocket
~TCPSocket() override
Definition: TCPSocket.cpp:73
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
lldb_private::TCPSocket::Listen
Status Listen(llvm::StringRef name, int backlog) override
Definition: TCPSocket.cpp:187