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