]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
Merge clang 7.0.1 and several follow-up changes
[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/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(_WIN32)
30 #include <winsock2.h>
31 #endif
32
33 #ifdef _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 }