Coverage Report

Created: 2022-01-18 06:27

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