Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp
39606 views
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
#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
static Status GetLastSocketError() {
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
74
TCPSocket::~TCPSocket() { CloseListenSockets(); }
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.
81
uint16_t TCPSocket::GetLocalPortNumber() const {
82
if (m_socket != kInvalidSocketValue) {
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
97
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
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
109
uint16_t TCPSocket::GetRemotePortNumber() const {
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
119
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
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
131
std::string TCPSocket::GetRemoteConnectionURI() const {
132
if (m_socket != kInvalidSocketValue) {
133
return std::string(llvm::formatv(
134
"connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
135
}
136
return "";
137
}
138
139
Status TCPSocket::CreateSocket(int domain) {
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,
146
m_child_processes_inherit, error);
147
return error;
148
}
149
150
Status TCPSocket::Connect(llvm::StringRef name) {
151
152
Log *log = GetLog(LLDBLog::Communication);
153
LLDB_LOG(log, "Connect to host/port {0}", name);
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 (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
171
&address.sockaddr(),
172
address.GetLength()) == -1) {
173
Close();
174
continue;
175
}
176
177
if (SetOptionNoDelay() == -1) {
178
Close();
179
continue;
180
}
181
182
error.Clear();
183
return error;
184
}
185
186
error.SetErrorString("Failed to connect port");
187
return error;
188
}
189
190
Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
191
Log *log = GetLog(LLDBLog::Connection);
192
LLDB_LOG(log, "Listen to {0}", name);
193
194
Status error;
195
llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
196
if (!host_port)
197
return Status(host_port.takeError());
198
199
if (host_port->hostname == "*")
200
host_port->hostname = "0.0.0.0";
201
std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
202
host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
203
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);
224
225
int err =
226
::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
227
if (err != -1)
228
err = ::listen(fd, backlog);
229
230
if (err == -1) {
231
error = GetLastSocketError();
232
CLOSE_SOCKET(fd);
233
continue;
234
}
235
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();
240
}
241
m_listen_sockets[fd] = address;
242
}
243
244
if (m_listen_sockets.empty()) {
245
assert(error.Fail());
246
return error;
247
}
248
return Status();
249
}
250
251
void TCPSocket::CloseListenSockets() {
252
for (auto socket : m_listen_sockets)
253
CLOSE_SOCKET(socket.first);
254
m_listen_sockets.clear();
255
}
256
257
Status TCPSocket::Accept(Socket *&conn_socket) {
258
Status error;
259
if (m_listen_sockets.size() == 0) {
260
error.SetErrorString("No open listening sockets!");
261
return error;
262
}
263
264
NativeSocket sock = kInvalidSocketValue;
265
NativeSocket listen_sock = kInvalidSocketValue;
266
lldb_private::SocketAddress AcceptAddr;
267
MainLoop accept_loop;
268
std::vector<MainLoopBase::ReadHandleUP> handles;
269
for (auto socket : m_listen_sockets) {
270
auto fd = socket.first;
271
auto inherit = this->m_child_processes_inherit;
272
auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
273
handles.emplace_back(accept_loop.RegisterReadObject(
274
io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
275
&listen_sock](MainLoopBase &loop) {
276
socklen_t sa_len = AcceptAddr.GetMaxLength();
277
sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
278
error);
279
listen_sock = fd;
280
loop.RequestTermination();
281
}, error));
282
if (error.Fail())
283
return error;
284
}
285
286
bool accept_connection = false;
287
std::unique_ptr<TCPSocket> accepted_socket;
288
// Loop until we are happy with our connection
289
while (!accept_connection) {
290
accept_loop.Run();
291
292
if (error.Fail())
293
return error;
294
295
lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
296
if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
297
if (sock != kInvalidSocketValue) {
298
CLOSE_SOCKET(sock);
299
sock = kInvalidSocketValue;
300
}
301
llvm::errs() << llvm::formatv(
302
"error: rejecting incoming connection from {0} (expecting {1})",
303
AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
304
continue;
305
}
306
accept_connection = true;
307
accepted_socket.reset(new TCPSocket(sock, *this));
308
}
309
310
if (!accepted_socket)
311
return error;
312
313
// Keep our TCP packets coming without any delays.
314
accepted_socket->SetOptionNoDelay();
315
error.Clear();
316
conn_socket = accepted_socket.release();
317
return error;
318
}
319
320
int TCPSocket::SetOptionNoDelay() {
321
return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
322
}
323
324
int TCPSocket::SetOptionReuseAddress() {
325
return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
326
}
327
328