TCPSocket.cpp revision 314564
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/Core/Log.h" 17#include "lldb/Host/Config.h" 18 19#ifndef LLDB_DISABLE_POSIX 20#include <arpa/inet.h> 21#include <netinet/tcp.h> 22#include <sys/socket.h> 23#endif 24 25using namespace lldb; 26using namespace lldb_private; 27 28namespace { 29 30const int kDomain = AF_INET; 31const int kType = SOCK_STREAM; 32} 33 34TCPSocket::TCPSocket(NativeSocket socket, bool should_close) 35 : Socket(socket, ProtocolTcp, should_close) {} 36 37TCPSocket::TCPSocket(bool child_processes_inherit, Error &error) 38 : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, 39 child_processes_inherit, error), 40 true) {} 41 42// Return the port number that is being used by the socket. 43uint16_t TCPSocket::GetLocalPortNumber() const { 44 if (m_socket != kInvalidSocketValue) { 45 SocketAddress sock_addr; 46 socklen_t sock_addr_len = sock_addr.GetMaxLength(); 47 if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) 48 return sock_addr.GetPort(); 49 } 50 return 0; 51} 52 53std::string TCPSocket::GetLocalIPAddress() const { 54 // We bound to port zero, so we need to figure out which port we actually 55 // bound to 56 if (m_socket != kInvalidSocketValue) { 57 SocketAddress sock_addr; 58 socklen_t sock_addr_len = sock_addr.GetMaxLength(); 59 if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) 60 return sock_addr.GetIPAddress(); 61 } 62 return ""; 63} 64 65uint16_t TCPSocket::GetRemotePortNumber() const { 66 if (m_socket != kInvalidSocketValue) { 67 SocketAddress sock_addr; 68 socklen_t sock_addr_len = sock_addr.GetMaxLength(); 69 if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) 70 return sock_addr.GetPort(); 71 } 72 return 0; 73} 74 75std::string TCPSocket::GetRemoteIPAddress() const { 76 // We bound to port zero, so we need to figure out which port we actually 77 // bound to 78 if (m_socket != kInvalidSocketValue) { 79 SocketAddress sock_addr; 80 socklen_t sock_addr_len = sock_addr.GetMaxLength(); 81 if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0) 82 return sock_addr.GetIPAddress(); 83 } 84 return ""; 85} 86 87Error TCPSocket::Connect(llvm::StringRef name) { 88 if (m_socket == kInvalidSocketValue) 89 return Error("Invalid socket"); 90 91 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); 92 if (log) 93 log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); 94 95 Error error; 96 std::string host_str; 97 std::string port_str; 98 int32_t port = INT32_MIN; 99 if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) 100 return error; 101 102 struct sockaddr_in sa; 103 ::memset(&sa, 0, sizeof(sa)); 104 sa.sin_family = kDomain; 105 sa.sin_port = htons(port); 106 107 int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); 108 109 if (inet_pton_result <= 0) { 110 struct hostent *host_entry = gethostbyname(host_str.c_str()); 111 if (host_entry) 112 host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list); 113 inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); 114 if (inet_pton_result <= 0) { 115 if (inet_pton_result == -1) 116 SetLastError(error); 117 else 118 error.SetErrorStringWithFormat("invalid host string: '%s'", 119 host_str.c_str()); 120 121 return error; 122 } 123 } 124 125 if (-1 == 126 ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) { 127 SetLastError(error); 128 return error; 129 } 130 131 // Keep our TCP packets coming without any delays. 132 SetOptionNoDelay(); 133 error.Clear(); 134 return error; 135} 136 137Error TCPSocket::Listen(llvm::StringRef name, int backlog) { 138 Error error; 139 140 // enable local address reuse 141 SetOptionReuseAddress(); 142 143 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 144 if (log) 145 log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data()); 146 147 std::string host_str; 148 std::string port_str; 149 int32_t port = INT32_MIN; 150 if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) 151 return error; 152 153 SocketAddress bind_addr; 154 155 // Only bind to the loopback address if we are expecting a connection from 156 // localhost to avoid any firewall issues. 157 const bool bind_addr_success = (host_str == "127.0.0.1") 158 ? bind_addr.SetToLocalhost(kDomain, port) 159 : bind_addr.SetToAnyAddress(kDomain, port); 160 161 if (!bind_addr_success) { 162 error.SetErrorString("Failed to bind port"); 163 return error; 164 } 165 166 int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength()); 167 if (err != -1) 168 err = ::listen(GetNativeSocket(), backlog); 169 170 if (err == -1) 171 SetLastError(error); 172 173 return error; 174} 175 176Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, 177 Socket *&conn_socket) { 178 Error error; 179 std::string host_str; 180 std::string port_str; 181 int32_t port; 182 if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) 183 return error; 184 185 const sa_family_t family = kDomain; 186 const int socktype = kType; 187 const int protocol = IPPROTO_TCP; 188 SocketAddress listen_addr; 189 if (host_str.empty()) 190 listen_addr.SetToLocalhost(family, port); 191 else if (host_str.compare("*") == 0) 192 listen_addr.SetToAnyAddress(family, port); 193 else { 194 if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, 195 socktype, protocol)) { 196 error.SetErrorStringWithFormat("unable to resolve hostname '%s'", 197 host_str.c_str()); 198 return error; 199 } 200 } 201 202 bool accept_connection = false; 203 std::unique_ptr<TCPSocket> accepted_socket; 204 205 // Loop until we are happy with our connection 206 while (!accept_connection) { 207 struct sockaddr_in accept_addr; 208 ::memset(&accept_addr, 0, sizeof accept_addr); 209#if !(defined(__linux__) || defined(_WIN32)) 210 accept_addr.sin_len = sizeof accept_addr; 211#endif 212 socklen_t accept_addr_len = sizeof accept_addr; 213 214 int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr, 215 &accept_addr_len, child_processes_inherit, error); 216 217 if (error.Fail()) 218 break; 219 220 bool is_same_addr = true; 221#if !(defined(__linux__) || (defined(_WIN32))) 222 is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); 223#endif 224 if (is_same_addr) 225 is_same_addr = (accept_addr.sin_addr.s_addr == 226 listen_addr.sockaddr_in().sin_addr.s_addr); 227 228 if (is_same_addr || 229 (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) { 230 accept_connection = true; 231 accepted_socket.reset(new TCPSocket(sock, true)); 232 } else { 233 const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; 234 const uint8_t *listen_ip = 235 (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; 236 ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u " 237 "(expecting %u.%u.%u.%u)\n", 238 accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], 239 listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); 240 accepted_socket.reset(); 241 } 242 } 243 244 if (!accepted_socket) 245 return error; 246 247 // Keep our TCP packets coming without any delays. 248 accepted_socket->SetOptionNoDelay(); 249 error.Clear(); 250 conn_socket = accepted_socket.release(); 251 return error; 252} 253 254int TCPSocket::SetOptionNoDelay() { 255 return SetOption(IPPROTO_TCP, TCP_NODELAY, 1); 256} 257 258int TCPSocket::SetOptionReuseAddress() { 259 return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); 260} 261