]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
Merge ^/head r312309 through r312623.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / common / TCPSocket.cpp
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
25 using namespace lldb;
26 using namespace lldb_private;
27
28 namespace {
29
30 const int kDomain = AF_INET;
31 const int kType = SOCK_STREAM;
32 }
33
34 TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
35     : Socket(socket, ProtocolTcp, should_close) {}
36
37 TCPSocket::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.
43 uint16_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
53 std::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
65 uint16_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
75 std::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
87 Error 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
137 Error 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
176 Error 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
254 int TCPSocket::SetOptionNoDelay() {
255   return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
256 }
257
258 int TCPSocket::SetOptionReuseAddress() {
259   return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
260 }