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