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