xref: /freebsd-src/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- TCPSocket.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #if defined(_MSC_VER)
100b57cec5SDimitry Andric #define _WINSOCK_DEPRECATED_NO_WARNINGS
110b57cec5SDimitry Andric #endif
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "lldb/Host/common/TCPSocket.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "lldb/Host/Config.h"
160b57cec5SDimitry Andric #include "lldb/Host/MainLoop.h"
1781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
180b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
210b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
225ffd83dbSDimitry Andric #include "llvm/Support/WindowsError.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric 
25480093f4SDimitry Andric #if LLDB_ENABLE_POSIX
260b57cec5SDimitry Andric #include <arpa/inet.h>
270b57cec5SDimitry Andric #include <netinet/tcp.h>
280b57cec5SDimitry Andric #include <sys/socket.h>
290b57cec5SDimitry Andric #endif
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #if defined(_WIN32)
320b57cec5SDimitry Andric #include <winsock2.h>
330b57cec5SDimitry Andric #endif
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #ifdef _WIN32
360b57cec5SDimitry Andric #define CLOSE_SOCKET closesocket
370b57cec5SDimitry Andric typedef const char *set_socket_option_arg_type;
380b57cec5SDimitry Andric #else
390b57cec5SDimitry Andric #include <unistd.h>
400b57cec5SDimitry Andric #define CLOSE_SOCKET ::close
410b57cec5SDimitry Andric typedef const void *set_socket_option_arg_type;
420b57cec5SDimitry Andric #endif
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric using namespace lldb;
450b57cec5SDimitry Andric using namespace lldb_private;
460b57cec5SDimitry Andric 
GetLastSocketError()475ffd83dbSDimitry Andric static Status GetLastSocketError() {
485ffd83dbSDimitry Andric   std::error_code EC;
495ffd83dbSDimitry Andric #ifdef _WIN32
505ffd83dbSDimitry Andric   EC = llvm::mapWindowsError(WSAGetLastError());
515ffd83dbSDimitry Andric #else
525ffd83dbSDimitry Andric   EC = std::error_code(errno, std::generic_category());
535ffd83dbSDimitry Andric #endif
545ffd83dbSDimitry Andric   return EC;
555ffd83dbSDimitry Andric }
565ffd83dbSDimitry Andric 
57349cc55cSDimitry Andric static const int kType = SOCK_STREAM;
580b57cec5SDimitry Andric 
TCPSocket(bool should_close,bool child_processes_inherit)590b57cec5SDimitry Andric TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
600b57cec5SDimitry Andric     : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
610b57cec5SDimitry Andric 
TCPSocket(NativeSocket socket,const TCPSocket & listen_socket)620b57cec5SDimitry Andric TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
630b57cec5SDimitry Andric     : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
640b57cec5SDimitry Andric              listen_socket.m_child_processes_inherit) {
650b57cec5SDimitry Andric   m_socket = socket;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
TCPSocket(NativeSocket socket,bool should_close,bool child_processes_inherit)680b57cec5SDimitry Andric TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
690b57cec5SDimitry Andric                      bool child_processes_inherit)
700b57cec5SDimitry Andric     : Socket(ProtocolTcp, should_close, child_processes_inherit) {
710b57cec5SDimitry Andric   m_socket = socket;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
~TCPSocket()740b57cec5SDimitry Andric TCPSocket::~TCPSocket() { CloseListenSockets(); }
750b57cec5SDimitry Andric 
IsValid() const760b57cec5SDimitry Andric bool TCPSocket::IsValid() const {
770b57cec5SDimitry Andric   return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric // Return the port number that is being used by the socket.
GetLocalPortNumber() const810b57cec5SDimitry Andric uint16_t TCPSocket::GetLocalPortNumber() const {
820b57cec5SDimitry Andric   if (m_socket != kInvalidSocketValue) {
830b57cec5SDimitry Andric     SocketAddress sock_addr;
840b57cec5SDimitry Andric     socklen_t sock_addr_len = sock_addr.GetMaxLength();
850b57cec5SDimitry Andric     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
860b57cec5SDimitry Andric       return sock_addr.GetPort();
870b57cec5SDimitry Andric   } else if (!m_listen_sockets.empty()) {
880b57cec5SDimitry Andric     SocketAddress sock_addr;
890b57cec5SDimitry Andric     socklen_t sock_addr_len = sock_addr.GetMaxLength();
900b57cec5SDimitry Andric     if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
910b57cec5SDimitry Andric                       &sock_addr_len) == 0)
920b57cec5SDimitry Andric       return sock_addr.GetPort();
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric   return 0;
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
GetLocalIPAddress() const970b57cec5SDimitry Andric std::string TCPSocket::GetLocalIPAddress() const {
980b57cec5SDimitry Andric   // We bound to port zero, so we need to figure out which port we actually
990b57cec5SDimitry Andric   // bound to
1000b57cec5SDimitry Andric   if (m_socket != kInvalidSocketValue) {
1010b57cec5SDimitry Andric     SocketAddress sock_addr;
1020b57cec5SDimitry Andric     socklen_t sock_addr_len = sock_addr.GetMaxLength();
1030b57cec5SDimitry Andric     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
1040b57cec5SDimitry Andric       return sock_addr.GetIPAddress();
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   return "";
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
GetRemotePortNumber() const1090b57cec5SDimitry Andric uint16_t TCPSocket::GetRemotePortNumber() const {
1100b57cec5SDimitry Andric   if (m_socket != kInvalidSocketValue) {
1110b57cec5SDimitry Andric     SocketAddress sock_addr;
1120b57cec5SDimitry Andric     socklen_t sock_addr_len = sock_addr.GetMaxLength();
1130b57cec5SDimitry Andric     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
1140b57cec5SDimitry Andric       return sock_addr.GetPort();
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric   return 0;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
GetRemoteIPAddress() const1190b57cec5SDimitry Andric std::string TCPSocket::GetRemoteIPAddress() const {
1200b57cec5SDimitry Andric   // We bound to port zero, so we need to figure out which port we actually
1210b57cec5SDimitry Andric   // bound to
1220b57cec5SDimitry Andric   if (m_socket != kInvalidSocketValue) {
1230b57cec5SDimitry Andric     SocketAddress sock_addr;
1240b57cec5SDimitry Andric     socklen_t sock_addr_len = sock_addr.GetMaxLength();
1250b57cec5SDimitry Andric     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
1260b57cec5SDimitry Andric       return sock_addr.GetIPAddress();
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric   return "";
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
GetRemoteConnectionURI() const1310b57cec5SDimitry Andric std::string TCPSocket::GetRemoteConnectionURI() const {
1320b57cec5SDimitry Andric   if (m_socket != kInvalidSocketValue) {
1335ffd83dbSDimitry Andric     return std::string(llvm::formatv(
1345ffd83dbSDimitry Andric         "connect://[{0}]:{1}", GetRemoteIPAddress(), GetRemotePortNumber()));
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric   return "";
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
CreateSocket(int domain)1390b57cec5SDimitry Andric Status TCPSocket::CreateSocket(int domain) {
1400b57cec5SDimitry Andric   Status error;
1410b57cec5SDimitry Andric   if (IsValid())
1420b57cec5SDimitry Andric     error = Close();
1430b57cec5SDimitry Andric   if (error.Fail())
1440b57cec5SDimitry Andric     return error;
1450b57cec5SDimitry Andric   m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
1460b57cec5SDimitry Andric                                   m_child_processes_inherit, error);
1470b57cec5SDimitry Andric   return error;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
Connect(llvm::StringRef name)1500b57cec5SDimitry Andric Status TCPSocket::Connect(llvm::StringRef name) {
1510b57cec5SDimitry Andric 
15281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Communication);
153*06c3fb27SDimitry Andric   LLDB_LOG(log, "Connect to host/port {0}", name);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   Status error;
156349cc55cSDimitry Andric   llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
157349cc55cSDimitry Andric   if (!host_port)
158349cc55cSDimitry Andric     return Status(host_port.takeError());
1590b57cec5SDimitry Andric 
160349cc55cSDimitry Andric   std::vector<SocketAddress> addresses =
161349cc55cSDimitry Andric       SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr,
162349cc55cSDimitry Andric                                     AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
163480093f4SDimitry Andric   for (SocketAddress &address : addresses) {
1640b57cec5SDimitry Andric     error = CreateSocket(address.GetFamily());
1650b57cec5SDimitry Andric     if (error.Fail())
1660b57cec5SDimitry Andric       continue;
1670b57cec5SDimitry Andric 
168349cc55cSDimitry Andric     address.SetPort(host_port->port);
1690b57cec5SDimitry Andric 
170bdd1243dSDimitry Andric     if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(),
171349cc55cSDimitry Andric                                     &address.sockaddr(),
172bdd1243dSDimitry Andric                                     address.GetLength()) == -1) {
17381ad6265SDimitry Andric       Close();
1740b57cec5SDimitry Andric       continue;
1750b57cec5SDimitry Andric     }
1760b57cec5SDimitry Andric 
177bdd1243dSDimitry Andric     if (SetOptionNoDelay() == -1) {
178bdd1243dSDimitry Andric       Close();
179bdd1243dSDimitry Andric       continue;
180bdd1243dSDimitry Andric     }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     error.Clear();
1830b57cec5SDimitry Andric     return error;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   error.SetErrorString("Failed to connect port");
1870b57cec5SDimitry Andric   return error;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
Listen(llvm::StringRef name,int backlog)1900b57cec5SDimitry Andric Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
19181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Connection);
192*06c3fb27SDimitry Andric   LLDB_LOG(log, "Listen to {0}", name);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   Status error;
195349cc55cSDimitry Andric   llvm::Expected<HostAndPort> host_port = DecodeHostAndPort(name);
196349cc55cSDimitry Andric   if (!host_port)
197349cc55cSDimitry Andric     return Status(host_port.takeError());
1980b57cec5SDimitry Andric 
199349cc55cSDimitry Andric   if (host_port->hostname == "*")
200349cc55cSDimitry Andric     host_port->hostname = "0.0.0.0";
201480093f4SDimitry Andric   std::vector<SocketAddress> addresses = SocketAddress::GetAddressInfo(
202349cc55cSDimitry Andric       host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
203480093f4SDimitry Andric   for (SocketAddress &address : addresses) {
2040b57cec5SDimitry Andric     int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
2050b57cec5SDimitry Andric                                   m_child_processes_inherit, error);
206bdd1243dSDimitry Andric     if (error.Fail() || fd < 0)
2070b57cec5SDimitry Andric       continue;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     // enable local address reuse
2100b57cec5SDimitry Andric     int option_value = 1;
2110b57cec5SDimitry Andric     set_socket_option_arg_type option_value_p =
2120b57cec5SDimitry Andric         reinterpret_cast<set_socket_option_arg_type>(&option_value);
213bdd1243dSDimitry Andric     if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
214bdd1243dSDimitry Andric                      sizeof(option_value)) == -1) {
215bdd1243dSDimitry Andric       CLOSE_SOCKET(fd);
216bdd1243dSDimitry Andric       continue;
217bdd1243dSDimitry Andric     }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     SocketAddress listen_address = address;
2200b57cec5SDimitry Andric     if(!listen_address.IsLocalhost())
221349cc55cSDimitry Andric       listen_address.SetToAnyAddress(address.GetFamily(), host_port->port);
2220b57cec5SDimitry Andric     else
223349cc55cSDimitry Andric       listen_address.SetPort(host_port->port);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric     int err =
2260b57cec5SDimitry Andric         ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
227bdd1243dSDimitry Andric     if (err != -1)
2280b57cec5SDimitry Andric       err = ::listen(fd, backlog);
2290b57cec5SDimitry Andric 
230bdd1243dSDimitry Andric     if (err == -1) {
2315ffd83dbSDimitry Andric       error = GetLastSocketError();
2320b57cec5SDimitry Andric       CLOSE_SOCKET(fd);
2330b57cec5SDimitry Andric       continue;
2340b57cec5SDimitry Andric     }
2350b57cec5SDimitry Andric 
236349cc55cSDimitry Andric     if (host_port->port == 0) {
2370b57cec5SDimitry Andric       socklen_t sa_len = address.GetLength();
2380b57cec5SDimitry Andric       if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
239349cc55cSDimitry Andric         host_port->port = address.GetPort();
2400b57cec5SDimitry Andric     }
2410b57cec5SDimitry Andric     m_listen_sockets[fd] = address;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2445ffd83dbSDimitry Andric   if (m_listen_sockets.empty()) {
2455ffd83dbSDimitry Andric     assert(error.Fail());
2460b57cec5SDimitry Andric     return error;
2470b57cec5SDimitry Andric   }
2485ffd83dbSDimitry Andric   return Status();
2495ffd83dbSDimitry Andric }
2500b57cec5SDimitry Andric 
CloseListenSockets()2510b57cec5SDimitry Andric void TCPSocket::CloseListenSockets() {
2520b57cec5SDimitry Andric   for (auto socket : m_listen_sockets)
2530b57cec5SDimitry Andric     CLOSE_SOCKET(socket.first);
2540b57cec5SDimitry Andric   m_listen_sockets.clear();
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
Accept(Socket * & conn_socket)2570b57cec5SDimitry Andric Status TCPSocket::Accept(Socket *&conn_socket) {
2580b57cec5SDimitry Andric   Status error;
2590b57cec5SDimitry Andric   if (m_listen_sockets.size() == 0) {
2600b57cec5SDimitry Andric     error.SetErrorString("No open listening sockets!");
2610b57cec5SDimitry Andric     return error;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
264bdd1243dSDimitry Andric   NativeSocket sock = kInvalidSocketValue;
265bdd1243dSDimitry Andric   NativeSocket listen_sock = kInvalidSocketValue;
2660b57cec5SDimitry Andric   lldb_private::SocketAddress AcceptAddr;
2670b57cec5SDimitry Andric   MainLoop accept_loop;
2680b57cec5SDimitry Andric   std::vector<MainLoopBase::ReadHandleUP> handles;
2690b57cec5SDimitry Andric   for (auto socket : m_listen_sockets) {
2700b57cec5SDimitry Andric     auto fd = socket.first;
2710b57cec5SDimitry Andric     auto inherit = this->m_child_processes_inherit;
2720b57cec5SDimitry Andric     auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
2730b57cec5SDimitry Andric     handles.emplace_back(accept_loop.RegisterReadObject(
2740b57cec5SDimitry Andric         io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
2750b57cec5SDimitry Andric                         &listen_sock](MainLoopBase &loop) {
2760b57cec5SDimitry Andric           socklen_t sa_len = AcceptAddr.GetMaxLength();
2770b57cec5SDimitry Andric           sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
2780b57cec5SDimitry Andric                               error);
2790b57cec5SDimitry Andric           listen_sock = fd;
2800b57cec5SDimitry Andric           loop.RequestTermination();
2810b57cec5SDimitry Andric         }, error));
2820b57cec5SDimitry Andric     if (error.Fail())
2830b57cec5SDimitry Andric       return error;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   bool accept_connection = false;
2870b57cec5SDimitry Andric   std::unique_ptr<TCPSocket> accepted_socket;
2880b57cec5SDimitry Andric   // Loop until we are happy with our connection
2890b57cec5SDimitry Andric   while (!accept_connection) {
2900b57cec5SDimitry Andric     accept_loop.Run();
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     if (error.Fail())
2930b57cec5SDimitry Andric         return error;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric     lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
2960b57cec5SDimitry Andric     if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
297bdd1243dSDimitry Andric       if (sock != kInvalidSocketValue) {
2980b57cec5SDimitry Andric         CLOSE_SOCKET(sock);
299bdd1243dSDimitry Andric         sock = kInvalidSocketValue;
300bdd1243dSDimitry Andric       }
3010b57cec5SDimitry Andric       llvm::errs() << llvm::formatv(
3020b57cec5SDimitry Andric           "error: rejecting incoming connection from {0} (expecting {1})",
3030b57cec5SDimitry Andric           AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
3040b57cec5SDimitry Andric       continue;
3050b57cec5SDimitry Andric     }
3060b57cec5SDimitry Andric     accept_connection = true;
3070b57cec5SDimitry Andric     accepted_socket.reset(new TCPSocket(sock, *this));
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   if (!accepted_socket)
3110b57cec5SDimitry Andric     return error;
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   // Keep our TCP packets coming without any delays.
3140b57cec5SDimitry Andric   accepted_socket->SetOptionNoDelay();
3150b57cec5SDimitry Andric   error.Clear();
3160b57cec5SDimitry Andric   conn_socket = accepted_socket.release();
3170b57cec5SDimitry Andric   return error;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
SetOptionNoDelay()3200b57cec5SDimitry Andric int TCPSocket::SetOptionNoDelay() {
3210b57cec5SDimitry Andric   return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
SetOptionReuseAddress()3240b57cec5SDimitry Andric int TCPSocket::SetOptionReuseAddress() {
3250b57cec5SDimitry Andric   return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
3260b57cec5SDimitry Andric }
327