xref: /openbsd-src/gnu/llvm/lldb/source/Host/common/TCPSocket.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- TCPSocket.cpp -----------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #if defined(_MSC_VER)
10061da546Spatrick #define _WINSOCK_DEPRECATED_NO_WARNINGS
11061da546Spatrick #endif
12061da546Spatrick 
13061da546Spatrick #include "lldb/Host/common/TCPSocket.h"
14061da546Spatrick 
15061da546Spatrick #include "lldb/Host/Config.h"
16061da546Spatrick #include "lldb/Host/MainLoop.h"
17*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
18061da546Spatrick #include "lldb/Utility/Log.h"
19061da546Spatrick 
20061da546Spatrick #include "llvm/Config/llvm-config.h"
21061da546Spatrick #include "llvm/Support/Errno.h"
22dda28197Spatrick #include "llvm/Support/WindowsError.h"
23061da546Spatrick #include "llvm/Support/raw_ostream.h"
24061da546Spatrick 
25061da546Spatrick #if LLDB_ENABLE_POSIX
26061da546Spatrick #include <arpa/inet.h>
27061da546Spatrick #include <netinet/tcp.h>
28061da546Spatrick #include <sys/socket.h>
29061da546Spatrick #endif
30061da546Spatrick 
31061da546Spatrick #if defined(_WIN32)
32061da546Spatrick #include <winsock2.h>
33061da546Spatrick #endif
34061da546Spatrick 
35061da546Spatrick #ifdef _WIN32
36061da546Spatrick #define CLOSE_SOCKET closesocket
37061da546Spatrick typedef const char *set_socket_option_arg_type;
38061da546Spatrick #else
39061da546Spatrick #include <unistd.h>
40061da546Spatrick #define CLOSE_SOCKET ::close
41061da546Spatrick typedef const void *set_socket_option_arg_type;
42061da546Spatrick #endif
43061da546Spatrick 
44061da546Spatrick using namespace lldb;
45061da546Spatrick using namespace lldb_private;
46061da546Spatrick 
GetLastSocketError()47dda28197Spatrick static Status GetLastSocketError() {
48dda28197Spatrick   std::error_code EC;
49dda28197Spatrick #ifdef _WIN32
50dda28197Spatrick   EC = llvm::mapWindowsError(WSAGetLastError());
51dda28197Spatrick #else
52dda28197Spatrick   EC = std::error_code(errno, std::generic_category());
53dda28197Spatrick #endif
54dda28197Spatrick   return EC;
55dda28197Spatrick }
56dda28197Spatrick 
57*f6aab3d8Srobert static const int kType = SOCK_STREAM;
58061da546Spatrick 
TCPSocket(bool should_close,bool child_processes_inherit)59061da546Spatrick TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
60061da546Spatrick     : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
61061da546Spatrick 
TCPSocket(NativeSocket socket,const TCPSocket & listen_socket)62061da546Spatrick TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
63061da546Spatrick     : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
64061da546Spatrick              listen_socket.m_child_processes_inherit) {
65061da546Spatrick   m_socket = socket;
66061da546Spatrick }
67061da546Spatrick 
TCPSocket(NativeSocket socket,bool should_close,bool child_processes_inherit)68061da546Spatrick TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
69061da546Spatrick                      bool child_processes_inherit)
70061da546Spatrick     : Socket(ProtocolTcp, should_close, child_processes_inherit) {
71061da546Spatrick   m_socket = socket;
72061da546Spatrick }
73061da546Spatrick 
~TCPSocket()74061da546Spatrick TCPSocket::~TCPSocket() { CloseListenSockets(); }
75061da546Spatrick 
IsValid() const76061da546Spatrick bool TCPSocket::IsValid() const {
77061da546Spatrick   return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
78061da546Spatrick }
79061da546Spatrick 
80061da546Spatrick // Return the port number that is being used by the socket.
GetLocalPortNumber() const81061da546Spatrick uint16_t TCPSocket::GetLocalPortNumber() const {
82061da546Spatrick   if (m_socket != kInvalidSocketValue) {
83061da546Spatrick     SocketAddress sock_addr;
84061da546Spatrick     socklen_t sock_addr_len = sock_addr.GetMaxLength();
85061da546Spatrick     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
86061da546Spatrick       return sock_addr.GetPort();
87061da546Spatrick   } else if (!m_listen_sockets.empty()) {
88061da546Spatrick     SocketAddress sock_addr;
89061da546Spatrick     socklen_t sock_addr_len = sock_addr.GetMaxLength();
90061da546Spatrick     if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
91061da546Spatrick                       &sock_addr_len) == 0)
92061da546Spatrick       return sock_addr.GetPort();
93061da546Spatrick   }
94061da546Spatrick   return 0;
95061da546Spatrick }
96061da546Spatrick 
GetLocalIPAddress() const97061da546Spatrick std::string TCPSocket::GetLocalIPAddress() const {
98061da546Spatrick   // We bound to port zero, so we need to figure out which port we actually
99061da546Spatrick   // bound to
100061da546Spatrick   if (m_socket != kInvalidSocketValue) {
101061da546Spatrick     SocketAddress sock_addr;
102061da546Spatrick     socklen_t sock_addr_len = sock_addr.GetMaxLength();
103061da546Spatrick     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
104061da546Spatrick       return sock_addr.GetIPAddress();
105061da546Spatrick   }
106061da546Spatrick   return "";
107061da546Spatrick }
108061da546Spatrick 
GetRemotePortNumber() const109061da546Spatrick uint16_t TCPSocket::GetRemotePortNumber() const {
110061da546Spatrick   if (m_socket != kInvalidSocketValue) {
111061da546Spatrick     SocketAddress sock_addr;
112061da546Spatrick     socklen_t sock_addr_len = sock_addr.GetMaxLength();
113061da546Spatrick     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
114061da546Spatrick       return sock_addr.GetPort();
115061da546Spatrick   }
116061da546Spatrick   return 0;
117061da546Spatrick }
118061da546Spatrick 
GetRemoteIPAddress() const119061da546Spatrick std::string TCPSocket::GetRemoteIPAddress() const {
120061da546Spatrick   // We bound to port zero, so we need to figure out which port we actually
121061da546Spatrick   // bound to
122061da546Spatrick   if (m_socket != kInvalidSocketValue) {
123061da546Spatrick     SocketAddress sock_addr;
124061da546Spatrick     socklen_t sock_addr_len = sock_addr.GetMaxLength();
125061da546Spatrick     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
126061da546Spatrick       return sock_addr.GetIPAddress();
127061da546Spatrick   }
128061da546Spatrick   return "";
129061da546Spatrick }
130061da546Spatrick 
GetRemoteConnectionURI() const131061da546Spatrick std::string TCPSocket::GetRemoteConnectionURI() const {
132061da546Spatrick   if (m_socket != kInvalidSocketValue) {
133dda28197Spatrick     return std::string(llvm::formatv(
134dda28197Spatrick         "connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
135061da546Spatrick   }
136061da546Spatrick   return "";
137061da546Spatrick }
138061da546Spatrick 
CreateSocket(int domain)139061da546Spatrick Status TCPSocket::CreateSocket(int domain) {
140061da546Spatrick   Status error;
141061da546Spatrick   if (IsValid())
142061da546Spatrick     error = Close();
143061da546Spatrick   if (error.Fail())
144061da546Spatrick     return error;
145061da546Spatrick   m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
146061da546Spatrick                                   m_child_processes_inherit, error);
147061da546Spatrick   return error;
148061da546Spatrick }
149061da546Spatrick 
Connect(llvm::StringRef name)150061da546Spatrick Status TCPSocket::Connect(llvm::StringRef name) {
151061da546Spatrick 
152*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Communication);
153061da546Spatrick   LLDB_LOGF(log, "TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
154061da546Spatrick 
155061da546Spatrick   Status error;
156*f6aab3d8Srobert   llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
157*f6aab3d8Srobert   if (!host_port)
158*f6aab3d8Srobert     return Status(host_port.takeError());
159061da546Spatrick 
160*f6aab3d8Srobert   std::vector<SocketAddress> addresses =
161*f6aab3d8Srobert       SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr,
162*f6aab3d8Srobert                                     AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
163061da546Spatrick   for (SocketAddress &address : addresses) {
164061da546Spatrick     error = CreateSocket(address.GetFamily());
165061da546Spatrick     if (error.Fail())
166061da546Spatrick       continue;
167061da546Spatrick 
168*f6aab3d8Srobert     address.SetPort(host_port->port);
169061da546Spatrick 
170*f6aab3d8Srobert     if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
171*f6aab3d8Srobert                                     &address.sockaddr(),
172*f6aab3d8Srobert                                     address.GetLength()) == -1) {
173*f6aab3d8Srobert       Close();
174061da546Spatrick       continue;
175061da546Spatrick     }
176061da546Spatrick 
177*f6aab3d8Srobert     if (SetOptionNoDelay() == -1) {
178*f6aab3d8Srobert       Close();
179*f6aab3d8Srobert       continue;
180*f6aab3d8Srobert     }
181061da546Spatrick 
182061da546Spatrick     error.Clear();
183061da546Spatrick     return error;
184061da546Spatrick   }
185061da546Spatrick 
186061da546Spatrick   error.SetErrorString("Failed to connect port");
187061da546Spatrick   return error;
188061da546Spatrick }
189061da546Spatrick 
Listen(llvm::StringRef name,int backlog)190061da546Spatrick Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
191*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Connection);
192061da546Spatrick   LLDB_LOGF(log, "TCPSocket::%s (%s)", __FUNCTION__, name.data());
193061da546Spatrick 
194061da546Spatrick   Status error;
195*f6aab3d8Srobert   llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
196*f6aab3d8Srobert   if (!host_port)
197*f6aab3d8Srobert     return Status(host_port.takeError());
198061da546Spatrick 
199*f6aab3d8Srobert   if (host_port->hostname == "*")
200*f6aab3d8Srobert     host_port->hostname = "0.0.0.0";
201061da546Spatrick   std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
202*f6aab3d8Srobert       host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
203061da546Spatrick   for (SocketAddress &address : addresses) {
204061da546Spatrick     int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
205061da546Spatrick                                   m_child_processes_inherit, error);
206*f6aab3d8Srobert     if (error.Fail() || fd < 0)
207061da546Spatrick       continue;
208061da546Spatrick 
209061da546Spatrick     // enable local address reuse
210061da546Spatrick     int option_value = 1;
211061da546Spatrick     set_socket_option_arg_type option_value_p =
212061da546Spatrick         reinterpret_cast<set_socket_option_arg_type>(&option_value);
213*f6aab3d8Srobert     if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
214*f6aab3d8Srobert                      sizeof(option_value)) == -1) {
215*f6aab3d8Srobert       CLOSE_SOCKET(fd);
216*f6aab3d8Srobert       continue;
217*f6aab3d8Srobert     }
218061da546Spatrick 
219061da546Spatrick     SocketAddress listen_address = address;
220061da546Spatrick     if(!listen_address.IsLocalhost())
221*f6aab3d8Srobert       listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
222061da546Spatrick     else
223*f6aab3d8Srobert       listen_address.SetPort(host_port->port);
224061da546Spatrick 
225061da546Spatrick     int err =
226061da546Spatrick         ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
227*f6aab3d8Srobert     if (err != -1)
228061da546Spatrick       err = ::listen(fd, backlog);
229061da546Spatrick 
230*f6aab3d8Srobert     if (err == -1) {
231dda28197Spatrick       error = GetLastSocketError();
232061da546Spatrick       CLOSE_SOCKET(fd);
233061da546Spatrick       continue;
234061da546Spatrick     }
235061da546Spatrick 
236*f6aab3d8Srobert     if (host_port->port == 0) {
237061da546Spatrick       socklen_t sa_len = address.GetLength();
238061da546Spatrick       if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
239*f6aab3d8Srobert         host_port->port = address.GetPort();
240061da546Spatrick     }
241061da546Spatrick     m_listen_sockets[fd] = address;
242061da546Spatrick   }
243061da546Spatrick 
244dda28197Spatrick   if (m_listen_sockets.empty()) {
245dda28197Spatrick     assert(error.Fail());
246061da546Spatrick     return error;
247061da546Spatrick   }
248dda28197Spatrick   return Status();
249dda28197Spatrick }
250061da546Spatrick 
CloseListenSockets()251061da546Spatrick void TCPSocket::CloseListenSockets() {
252061da546Spatrick   for (auto socket : m_listen_sockets)
253061da546Spatrick     CLOSE_SOCKET(socket.first);
254061da546Spatrick   m_listen_sockets.clear();
255061da546Spatrick }
256061da546Spatrick 
Accept(Socket * & conn_socket)257061da546Spatrick Status TCPSocket::Accept(Socket *&conn_socket) {
258061da546Spatrick   Status error;
259061da546Spatrick   if (m_listen_sockets.size() == 0) {
260061da546Spatrick     error.SetErrorString("No open listening sockets!");
261061da546Spatrick     return error;
262061da546Spatrick   }
263061da546Spatrick 
264*f6aab3d8Srobert   NativeSocket sock = kInvalidSocketValue;
265*f6aab3d8Srobert   NativeSocket listen_sock = kInvalidSocketValue;
266061da546Spatrick   lldb_private::SocketAddress AcceptAddr;
267061da546Spatrick   MainLoop accept_loop;
268061da546Spatrick   std::vector<MainLoopBase::ReadHandleUP> handles;
269061da546Spatrick   for (auto socket : m_listen_sockets) {
270061da546Spatrick     auto fd = socket.first;
271061da546Spatrick     auto inherit = this->m_child_processes_inherit;
272061da546Spatrick     auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
273061da546Spatrick     handles.emplace_back(accept_loop.RegisterReadObject(
274061da546Spatrick         io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
275061da546Spatrick                         &listen_sock](MainLoopBase &loop) {
276061da546Spatrick           socklen_t sa_len = AcceptAddr.GetMaxLength();
277061da546Spatrick           sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
278061da546Spatrick                               error);
279061da546Spatrick           listen_sock = fd;
280061da546Spatrick           loop.RequestTermination();
281061da546Spatrick         }, error));
282061da546Spatrick     if (error.Fail())
283061da546Spatrick       return error;
284061da546Spatrick   }
285061da546Spatrick 
286061da546Spatrick   bool accept_connection = false;
287061da546Spatrick   std::unique_ptr<TCPSocket> accepted_socket;
288061da546Spatrick   // Loop until we are happy with our connection
289061da546Spatrick   while (!accept_connection) {
290061da546Spatrick     accept_loop.Run();
291061da546Spatrick 
292061da546Spatrick     if (error.Fail())
293061da546Spatrick         return error;
294061da546Spatrick 
295061da546Spatrick     lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
296061da546Spatrick     if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
297*f6aab3d8Srobert       if (sock != kInvalidSocketValue) {
298061da546Spatrick         CLOSE_SOCKET(sock);
299*f6aab3d8Srobert         sock = kInvalidSocketValue;
300*f6aab3d8Srobert       }
301061da546Spatrick       llvm::errs() << llvm::formatv(
302061da546Spatrick           "error: rejecting incoming connection from {0} (expecting {1})",
303061da546Spatrick           AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
304061da546Spatrick       continue;
305061da546Spatrick     }
306061da546Spatrick     accept_connection = true;
307061da546Spatrick     accepted_socket.reset(new TCPSocket(sock, *this));
308061da546Spatrick   }
309061da546Spatrick 
310061da546Spatrick   if (!accepted_socket)
311061da546Spatrick     return error;
312061da546Spatrick 
313061da546Spatrick   // Keep our TCP packets coming without any delays.
314061da546Spatrick   accepted_socket->SetOptionNoDelay();
315061da546Spatrick   error.Clear();
316061da546Spatrick   conn_socket = accepted_socket.release();
317061da546Spatrick   return error;
318061da546Spatrick }
319061da546Spatrick 
SetOptionNoDelay()320061da546Spatrick int TCPSocket::SetOptionNoDelay() {
321061da546Spatrick   return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
322061da546Spatrick }
323061da546Spatrick 
SetOptionReuseAddress()324061da546Spatrick int TCPSocket::SetOptionReuseAddress() {
325061da546Spatrick   return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
326061da546Spatrick }
327