Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Host/common/TCPSocket.cpp
Line
Count
Source (jump to first uncovered line)
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
13
#include "lldb/Host/common/TCPSocket.h"
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
108
#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
47
0
static Status GetLastSocketError() {
48
0
  std::error_code EC;
49
#ifdef _WIN32
50
  EC = llvm::mapWindowsError(WSAGetLastError());
51
#else
52
0
  EC = std::error_code(errno, std::generic_category());
53
0
#endif
54
0
  return EC;
55
0
}
56
57
static const int kType = SOCK_STREAM;
58
59
TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
60
246
    : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
61
62
TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
63
50
    : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
64
50
             listen_socket.m_child_processes_inherit) {
65
50
  m_socket = socket;
66
50
}
67
68
TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
69
                     bool child_processes_inherit)
70
90
    : Socket(ProtocolTcp, should_close, child_processes_inherit) {
71
90
  m_socket = socket;
72
90
}
73
74
386
TCPSocket::~TCPSocket() { CloseListenSockets(); }
75
76
792k
bool TCPSocket::IsValid() const {
77
792k
  return m_socket != kInvalidSocketValue || 
m_listen_sockets.size() != 01.89k
;
78
792k
}
79
80
// Return the port number that is being used by the socket.
81
60
uint16_t TCPSocket::GetLocalPortNumber() const {
82
60
  if (m_socket != kInvalidSocketValue) {
83
8
    SocketAddress sock_addr;
84
8
    socklen_t sock_addr_len = sock_addr.GetMaxLength();
85
8
    if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
86
8
      return sock_addr.GetPort();
87
52
  } else if (!m_listen_sockets.empty()) {
88
52
    SocketAddress sock_addr;
89
52
    socklen_t sock_addr_len = sock_addr.GetMaxLength();
90
52
    if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
91
52
                      &sock_addr_len) == 0)
92
52
      return sock_addr.GetPort();
93
52
  }
94
0
  return 0;
95
60
}
96
97
0
std::string TCPSocket::GetLocalIPAddress() const {
98
  // We bound to port zero, so we need to figure out which port we actually
99
  // bound to
100
0
  if (m_socket != kInvalidSocketValue) {
101
0
    SocketAddress sock_addr;
102
0
    socklen_t sock_addr_len = sock_addr.GetMaxLength();
103
0
    if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
104
0
      return sock_addr.GetIPAddress();
105
0
  }
106
0
  return "";
107
0
}
108
109
44
uint16_t TCPSocket::GetRemotePortNumber() const {
110
44
  if (m_socket != kInvalidSocketValue) {
111
44
    SocketAddress sock_addr;
112
44
    socklen_t sock_addr_len = sock_addr.GetMaxLength();
113
44
    if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
114
44
      return sock_addr.GetPort();
115
44
  }
116
0
  return 0;
117
44
}
118
119
40
std::string TCPSocket::GetRemoteIPAddress() const {
120
  // We bound to port zero, so we need to figure out which port we actually
121
  // bound to
122
40
  if (m_socket != kInvalidSocketValue) {
123
40
    SocketAddress sock_addr;
124
40
    socklen_t sock_addr_len = sock_addr.GetMaxLength();
125
40
    if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
126
40
      return sock_addr.GetIPAddress();
127
40
  }
128
0
  return "";
129
40
}
130
131
36
std::string TCPSocket::GetRemoteConnectionURI() const {
132
36
  if (m_socket != kInvalidSocketValue) {
133
36
    return std::string(llvm::formatv(
134
36
        "connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
135
36
  }
136
0
  return "";
137
36
}
138
139
180
Status TCPSocket::CreateSocket(int domain) {
140
180
  Status error;
141
180
  if (IsValid())
142
0
    error = Close();
143
180
  if (error.Fail())
144
0
    return error;
145
180
  m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
146
180
                                  m_child_processes_inherit, error);
147
180
  return error;
148
180
}
149
150
178
Status TCPSocket::Connect(llvm::StringRef name) {
151
152
178
  Log *log = GetLog(LLDBLog::Communication);
153
178
  LLDB_LOG(log, "Connect to host/port {0}", name);
154
155
178
  Status error;
156
178
  llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
157
178
  if (!host_port)
158
0
    return Status(host_port.takeError());
159
160
178
  std::vector<SocketAddress> addresses =
161
178
      SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr,
162
178
                                    AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
163
180
  for (SocketAddress &address : addresses) {
164
180
    error = CreateSocket(address.GetFamily());
165
180
    if (error.Fail())
166
0
      continue;
167
168
180
    address.SetPort(host_port->port);
169
170
180
    if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
171
180
                                    &address.sockaddr(),
172
180
                                    address.GetLength()) == -1) {
173
4
      Close();
174
4
      continue;
175
4
    }
176
177
176
    if (SetOptionNoDelay() == -1) {
178
0
      Close();
179
0
      continue;
180
0
    }
181
182
176
    error.Clear();
183
176
    return error;
184
176
  }
185
186
2
  error.SetErrorString("Failed to connect port");
187
2
  return error;
188
178
}
189
190
68
Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
191
68
  Log *log = GetLog(LLDBLog::Connection);
192
68
  LLDB_LOG(log, "Listen to {0}", name);
193
194
68
  Status error;
195
68
  llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
196
68
  if (!host_port)
197
0
    return Status(host_port.takeError());
198
199
68
  if (host_port->hostname == "*")
200
0
    host_port->hostname = "0.0.0.0";
201
68
  std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
202
68
      host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
203
108
  for (SocketAddress &address : addresses) {
204
108
    int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
205
108
                                  m_child_processes_inherit, error);
206
108
    if (error.Fail() || fd < 0)
207
0
      continue;
208
209
    // enable local address reuse
210
108
    int option_value = 1;
211
108
    set_socket_option_arg_type option_value_p =
212
108
        reinterpret_cast<set_socket_option_arg_type>(&option_value);
213
108
    if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
214
108
                     sizeof(option_value)) == -1) {
215
0
      CLOSE_SOCKET(fd);
216
0
      continue;
217
0
    }
218
219
108
    SocketAddress listen_address = address;
220
108
    if(!listen_address.IsLocalhost())
221
2
      listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
222
106
    else
223
106
      listen_address.SetPort(host_port->port);
224
225
108
    int err =
226
108
        ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
227
108
    if (err != -1)
228
108
      err = ::listen(fd, backlog);
229
230
108
    if (err == -1) {
231
0
      error = GetLastSocketError();
232
0
      CLOSE_SOCKET(fd);
233
0
      continue;
234
0
    }
235
236
108
    if (host_port->port == 0) {
237
68
      socklen_t sa_len = address.GetLength();
238
68
      if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
239
68
        host_port->port = address.GetPort();
240
68
    }
241
108
    m_listen_sockets[fd] = address;
242
108
  }
243
244
68
  if (m_listen_sockets.empty()) {
245
0
    assert(error.Fail());
246
0
    return error;
247
0
  }
248
68
  return Status();
249
68
}
250
251
386
void TCPSocket::CloseListenSockets() {
252
386
  for (auto socket : m_listen_sockets)
253
108
    CLOSE_SOCKET(socket.first);
254
386
  m_listen_sockets.clear();
255
386
}
256
257
50
Status TCPSocket::Accept(Socket *&conn_socket) {
258
50
  Status error;
259
50
  if (m_listen_sockets.size() == 0) {
260
0
    error.SetErrorString("No open listening sockets!");
261
0
    return error;
262
0
  }
263
264
50
  NativeSocket sock = kInvalidSocketValue;
265
50
  NativeSocket listen_sock = kInvalidSocketValue;
266
50
  lldb_private::SocketAddress AcceptAddr;
267
50
  MainLoop accept_loop;
268
50
  std::vector<MainLoopBase::ReadHandleUP> handles;
269
90
  for (auto socket : m_listen_sockets) {
270
90
    auto fd = socket.first;
271
90
    auto inherit = this->m_child_processes_inherit;
272
90
    auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
273
90
    handles.emplace_back(accept_loop.RegisterReadObject(
274
90
        io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
275
90
                        &listen_sock](MainLoopBase &loop) {
276
50
          socklen_t sa_len = AcceptAddr.GetMaxLength();
277
50
          sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
278
50
                              error);
279
50
          listen_sock = fd;
280
50
          loop.RequestTermination();
281
50
        }, error));
282
90
    if (error.Fail())
283
0
      return error;
284
90
  }
285
286
50
  bool accept_connection = false;
287
50
  std::unique_ptr<TCPSocket> accepted_socket;
288
  // Loop until we are happy with our connection
289
100
  while (!accept_connection) {
290
50
    accept_loop.Run();
291
292
50
    if (error.Fail())
293
0
        return error;
294
295
50
    lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
296
50
    if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
297
0
      if (sock != kInvalidSocketValue) {
298
0
        CLOSE_SOCKET(sock);
299
0
        sock = kInvalidSocketValue;
300
0
      }
301
0
      llvm::errs() << llvm::formatv(
302
0
          "error: rejecting incoming connection from {0} (expecting {1})",
303
0
          AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
304
0
      continue;
305
0
    }
306
50
    accept_connection = true;
307
50
    accepted_socket.reset(new TCPSocket(sock, *this));
308
50
  }
309
310
50
  if (!accepted_socket)
311
0
    return error;
312
313
  // Keep our TCP packets coming without any delays.
314
50
  accepted_socket->SetOptionNoDelay();
315
50
  error.Clear();
316
50
  conn_socket = accepted_socket.release();
317
50
  return error;
318
50
}
319
320
226
int TCPSocket::SetOptionNoDelay() {
321
226
  return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
322
226
}
323
324
0
int TCPSocket::SetOptionReuseAddress() {
325
0
  return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
326
0
}