1 //===-- TCPSocket.cpp -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #if defined(_MSC_VER)
10 #define _WINSOCK_DEPRECATED_NO_WARNINGS
11 #endif
12 
13 #include "lldb/Host/common/TCPSocket.h"
14 
15 #include "lldb/Host/Config.h"
16 #include "lldb/Host/MainLoop.h"
17 #include "lldb/Utility/Log.h"
18 
19 #include "llvm/Config/llvm-config.h"
20 #include "llvm/Support/raw_ostream.h"
21 
22 #ifndef LLDB_DISABLE_POSIX
23 #include <arpa/inet.h>
24 #include <netinet/tcp.h>
25 #include <sys/socket.h>
26 #endif
27 
28 #if defined(_WIN32)
29 #include <winsock2.h>
30 #endif
31 
32 #ifdef _WIN32
33 #define CLOSE_SOCKET closesocket
34 typedef const char *set_socket_option_arg_type;
35 #else
36 #include <unistd.h>
37 #define CLOSE_SOCKET ::close
38 typedef const void *set_socket_option_arg_type;
39 #endif
40 
41 using namespace lldb;
42 using namespace lldb_private;
43 
44 namespace {
45 const int kType = SOCK_STREAM;
46 }
47 
48 TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
49     : Socket(ProtocolTcp, should_close, child_processes_inherit) {}
50 
51 TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
52     : Socket(ProtocolTcp, listen_socket.m_should_close_fd,
53              listen_socket.m_child_processes_inherit) {
54   m_socket = socket;
55 }
56 
57 TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
58                      bool child_processes_inherit)
59     : Socket(ProtocolTcp, should_close, child_processes_inherit) {
60   m_socket = socket;
61 }
62 
63 TCPSocket::~TCPSocket() { CloseListenSockets(); }
64 
65 bool TCPSocket::IsValid() const {
66   return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
67 }
68 
69 // Return the port number that is being used by the socket.
70 uint16_t TCPSocket::GetLocalPortNumber() const {
71   if (m_socket != kInvalidSocketValue) {
72     SocketAddress sock_addr;
73     socklen_t sock_addr_len = sock_addr.GetMaxLength();
74     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
75       return sock_addr.GetPort();
76   } else if (!m_listen_sockets.empty()) {
77     SocketAddress sock_addr;
78     socklen_t sock_addr_len = sock_addr.GetMaxLength();
79     if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
80                       &sock_addr_len) == 0)
81       return sock_addr.GetPort();
82   }
83   return 0;
84 }
85 
86 std::string TCPSocket::GetLocalIPAddress() const {
87   // We bound to port zero, so we need to figure out which port we actually
88   // bound to
89   if (m_socket != kInvalidSocketValue) {
90     SocketAddress sock_addr;
91     socklen_t sock_addr_len = sock_addr.GetMaxLength();
92     if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
93       return sock_addr.GetIPAddress();
94   }
95   return "";
96 }
97 
98 uint16_t TCPSocket::GetRemotePortNumber() const {
99   if (m_socket != kInvalidSocketValue) {
100     SocketAddress sock_addr;
101     socklen_t sock_addr_len = sock_addr.GetMaxLength();
102     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
103       return sock_addr.GetPort();
104   }
105   return 0;
106 }
107 
108 std::string TCPSocket::GetRemoteIPAddress() const {
109   // We bound to port zero, so we need to figure out which port we actually
110   // bound to
111   if (m_socket != kInvalidSocketValue) {
112     SocketAddress sock_addr;
113     socklen_t sock_addr_len = sock_addr.GetMaxLength();
114     if (::getpeername(m_socket, sock_addr, &sock_addr_len) == 0)
115       return sock_addr.GetIPAddress();
116   }
117   return "";
118 }
119 
120 Status TCPSocket::CreateSocket(int domain) {
121   Status error;
122   if (IsValid())
123     error = Close();
124   if (error.Fail())
125     return error;
126   m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
127                                   m_child_processes_inherit, error);
128   return error;
129 }
130 
131 Status TCPSocket::Connect(llvm::StringRef name) {
132 
133   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION));
134   if (log)
135     log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
136 
137   Status error;
138   std::string host_str;
139   std::string port_str;
140   int32_t port = INT32_MIN;
141   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
142     return error;
143 
144   auto addresses = lldb_private::SocketAddress::GetAddressInfo(
145       host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
146   for (auto address : addresses) {
147     error = CreateSocket(address.GetFamily());
148     if (error.Fail())
149       continue;
150 
151     address.SetPort(port);
152 
153     if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(),
154                         address.GetLength())) {
155       CLOSE_SOCKET(GetNativeSocket());
156       continue;
157     }
158 
159     SetOptionNoDelay();
160 
161     error.Clear();
162     return error;
163   }
164 
165   error.SetErrorString("Failed to connect port");
166   return error;
167 }
168 
169 Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
170   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
171   if (log)
172     log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data());
173 
174   Status error;
175   std::string host_str;
176   std::string port_str;
177   int32_t port = INT32_MIN;
178   if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
179     return error;
180 
181   if (host_str == "*")
182     host_str = "0.0.0.0";
183   auto addresses = lldb_private::SocketAddress::GetAddressInfo(
184       host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
185   for (auto address : addresses) {
186     int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
187                                   m_child_processes_inherit, error);
188     if (error.Fail()) {
189       error.Clear();
190       continue;
191     }
192 
193     // enable local address reuse
194     int option_value = 1;
195     set_socket_option_arg_type option_value_p =
196         reinterpret_cast<set_socket_option_arg_type>(&option_value);
197     ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
198                  sizeof(option_value));
199 
200     SocketAddress listen_address = address;
201     if(!listen_address.IsLocalhost())
202       listen_address.SetToAnyAddress(address.GetFamily(), port);
203     else
204       listen_address.SetPort(port);
205 
206     int err =
207         ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength());
208     if (-1 != err)
209       err = ::listen(fd, backlog);
210 
211     if (-1 == err) {
212       CLOSE_SOCKET(fd);
213       continue;
214     }
215 
216     if (port == 0) {
217       socklen_t sa_len = address.GetLength();
218       if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
219         port = address.GetPort();
220     }
221     m_listen_sockets[fd] = address;
222   }
223 
224   if (m_listen_sockets.size() == 0)
225     error.SetErrorString("Failed to connect port");
226   return error;
227 }
228 
229 void TCPSocket::CloseListenSockets() {
230   for (auto socket : m_listen_sockets)
231   CLOSE_SOCKET(socket.first);
232   m_listen_sockets.clear();
233 }
234 
235 Status TCPSocket::Accept(Socket *&conn_socket) {
236   Status error;
237   if (m_listen_sockets.size() == 0) {
238     error.SetErrorString("No open listening sockets!");
239     return error;
240   }
241 
242   int sock = -1;
243   int listen_sock = -1;
244   lldb_private::SocketAddress AcceptAddr;
245   MainLoop accept_loop;
246   std::vector<MainLoopBase::ReadHandleUP> handles;
247   for (auto socket : m_listen_sockets) {
248     auto fd = socket.first;
249     auto inherit = this->m_child_processes_inherit;
250     auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
251     handles.emplace_back(accept_loop.RegisterReadObject(
252         io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
253                         &listen_sock](MainLoopBase &loop) {
254           socklen_t sa_len = AcceptAddr.GetMaxLength();
255           sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
256                               error);
257           listen_sock = fd;
258           loop.RequestTermination();
259         }, error));
260     if (error.Fail())
261       return error;
262   }
263 
264   bool accept_connection = false;
265   std::unique_ptr<TCPSocket> accepted_socket;
266   // Loop until we are happy with our connection
267   while (!accept_connection) {
268     accept_loop.Run();
269 
270     if (error.Fail())
271         return error;
272 
273     lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
274     if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
275       CLOSE_SOCKET(sock);
276       llvm::errs() << llvm::formatv(
277           "error: rejecting incoming connection from {0} (expecting {1})",
278           AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
279       continue;
280     }
281     accept_connection = true;
282     accepted_socket.reset(new TCPSocket(sock, *this));
283   }
284 
285   if (!accepted_socket)
286     return error;
287 
288   // Keep our TCP packets coming without any delays.
289   accepted_socket->SetOptionNoDelay();
290   error.Clear();
291   conn_socket = accepted_socket.release();
292   return error;
293 }
294 
295 int TCPSocket::SetOptionNoDelay() {
296   return SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
297 }
298 
299 int TCPSocket::SetOptionReuseAddress() {
300   return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
301 }
302