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