1 //===-- TCPSocket.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #if defined(_MSC_VER) 11 #define _WINSOCK_DEPRECATED_NO_WARNINGS 12 #endif 13 14 #include "lldb/Host/common/TCPSocket.h" 15 16 #include "lldb/Host/Config.h" 17 #include "lldb/Host/MainLoop.h" 18 #include "lldb/Utility/Log.h" 19 20 #include "llvm/Config/llvm-config.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 #ifndef LLDB_DISABLE_POSIX 24 #include <arpa/inet.h> 25 #include <netinet/tcp.h> 26 #include <sys/socket.h> 27 #endif 28 29 #if defined(LLVM_ON_WIN32) 30 #include <winsock2.h> 31 #endif 32 33 #ifdef LLVM_ON_WIN32 34 #define CLOSE_SOCKET closesocket 35 typedef const char *set_socket_option_arg_type; 36 #else 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 address.SetPort(port); 201 202 int err = ::bind(fd, &address.sockaddr(), address.GetLength()); 203 if (-1 != err) 204 err = ::listen(fd, backlog); 205 206 if (-1 == err) { 207 CLOSE_SOCKET(fd); 208 continue; 209 } 210 211 if (port == 0) { 212 socklen_t sa_len = address.GetLength(); 213 if (getsockname(fd, &address.sockaddr(), &sa_len) == 0) 214 port = address.GetPort(); 215 } 216 m_listen_sockets[fd] = address; 217 } 218 219 if (m_listen_sockets.size() == 0) 220 error.SetErrorString("Failed to connect port"); 221 return error; 222 } 223 224 void TCPSocket::CloseListenSockets() { 225 for (auto socket : m_listen_sockets) 226 CLOSE_SOCKET(socket.first); 227 m_listen_sockets.clear(); 228 } 229 230 Status TCPSocket::Accept(Socket *&conn_socket) { 231 Status error; 232 if (m_listen_sockets.size() == 0) { 233 error.SetErrorString("No open listening sockets!"); 234 return error; 235 } 236 237 int sock = -1; 238 int listen_sock = -1; 239 lldb_private::SocketAddress AcceptAddr; 240 MainLoop accept_loop; 241 std::vector<MainLoopBase::ReadHandleUP> handles; 242 for (auto socket : m_listen_sockets) { 243 auto fd = socket.first; 244 auto inherit = this->m_child_processes_inherit; 245 auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit)); 246 handles.emplace_back(accept_loop.RegisterReadObject( 247 io_sp, [fd, inherit, &sock, &AcceptAddr, &error, 248 &listen_sock](MainLoopBase &loop) { 249 socklen_t sa_len = AcceptAddr.GetMaxLength(); 250 sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit, 251 error); 252 listen_sock = fd; 253 loop.RequestTermination(); 254 }, error)); 255 if (error.Fail()) 256 return error; 257 } 258 259 bool accept_connection = false; 260 std::unique_ptr<TCPSocket> accepted_socket; 261 // Loop until we are happy with our connection 262 while (!accept_connection) { 263 accept_loop.Run(); 264 265 if (error.Fail()) 266 return error; 267 268 lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock]; 269 if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) { 270 CLOSE_SOCKET(sock); 271 llvm::errs() << llvm::formatv( 272 "error: rejecting incoming connection from {0} (expecting {1})", 273 AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress()); 274 continue; 275 } 276 accept_connection = true; 277 accepted_socket.reset(new TCPSocket(sock, *this)); 278 } 279 280 if (!accepted_socket) 281 return error; 282 283 // Keep our TCP packets coming without any delays. 284 accepted_socket->SetOptionNoDelay(); 285 error.Clear(); 286 conn_socket = accepted_socket.release(); 287 return error; 288 } 289 290 int TCPSocket::SetOptionNoDelay() { 291 return SetOption(IPPROTO_TCP, TCP_NODELAY, 1); 292 } 293 294 int TCPSocket::SetOptionReuseAddress() { 295 return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); 296 } 297