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