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