]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
MFV r311899:
[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 #include "lldb/Host/common/TCPSocket.h"
11
12 #include "lldb/Core/Log.h"
13 #include "lldb/Host/Config.h"
14
15 #ifndef LLDB_DISABLE_POSIX
16 #include <arpa/inet.h>
17 #include <netinet/tcp.h>
18 #include <sys/socket.h>
19 #endif
20
21 using namespace lldb;
22 using namespace lldb_private;
23
24 namespace {
25
26 const int kDomain = AF_INET;
27 const int kType   = SOCK_STREAM;
28
29 }
30
31 TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
32     : Socket(socket, ProtocolTcp, should_close)
33 {
34
35 }
36
37 TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
38     : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true)
39 {
40 }
41
42
43 // Return the port number that is being used by the socket.
44 uint16_t
45 TCPSocket::GetLocalPortNumber() const
46 {
47     if (m_socket != kInvalidSocketValue)
48     {
49         SocketAddress sock_addr;
50         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
51         if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
52             return sock_addr.GetPort ();
53     }
54     return 0;
55 }
56
57 std::string
58 TCPSocket::GetLocalIPAddress() const
59 {
60     // We bound to port zero, so we need to figure out which port we actually bound to
61     if (m_socket != kInvalidSocketValue)
62     {
63         SocketAddress sock_addr;
64         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
65         if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
66             return sock_addr.GetIPAddress ();
67     }
68     return "";
69 }
70
71 uint16_t
72 TCPSocket::GetRemotePortNumber() const
73 {
74     if (m_socket != kInvalidSocketValue)
75     {
76         SocketAddress sock_addr;
77         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
78         if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
79             return sock_addr.GetPort ();
80     }
81     return 0;
82 }
83
84 std::string
85 TCPSocket::GetRemoteIPAddress () const
86 {
87     // We bound to port zero, so we need to figure out which port we actually bound to
88     if (m_socket != kInvalidSocketValue)
89     {
90         SocketAddress sock_addr;
91         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
92         if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
93             return sock_addr.GetIPAddress ();
94     }
95     return "";
96 }
97
98 Error
99 TCPSocket::Connect(llvm::StringRef name)
100 {
101     if (m_socket == kInvalidSocketValue)
102         return Error("Invalid socket");
103
104     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
105     if (log)
106         log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
107
108     Error error;
109     std::string host_str;
110     std::string port_str;
111     int32_t port = INT32_MIN;
112     if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
113         return error;
114
115     struct sockaddr_in sa;
116     ::memset (&sa, 0, sizeof (sa));
117     sa.sin_family = kDomain;
118     sa.sin_port = htons (port);
119
120     int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
121
122     if (inet_pton_result <= 0)
123     {
124         struct hostent *host_entry = gethostbyname (host_str.c_str());
125         if (host_entry)
126             host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
127         inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
128         if (inet_pton_result <= 0)
129         {
130             if (inet_pton_result == -1)
131                 SetLastError(error);
132             else
133                 error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
134
135             return error;
136         }
137     }
138
139     if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa)))
140     {
141         SetLastError (error);
142         return error;
143     }
144
145     // Keep our TCP packets coming without any delays.
146     SetOptionNoDelay();
147     error.Clear();
148     return error;
149 }
150
151 Error
152 TCPSocket::Listen(llvm::StringRef name, int backlog)
153 {
154     Error error;
155
156     // enable local address reuse
157     SetOptionReuseAddress();
158
159     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
160     if (log)
161         log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data());
162
163     std::string host_str;
164     std::string port_str;
165     int32_t port = INT32_MIN;
166     if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
167         return error;
168
169     SocketAddress bind_addr;
170
171     // Only bind to the loopback address if we are expecting a connection from
172     // localhost to avoid any firewall issues.
173     const bool bind_addr_success = (host_str == "127.0.0.1") ?
174                                     bind_addr.SetToLocalhost (kDomain, port) :
175                                     bind_addr.SetToAnyAddress (kDomain, port);
176
177     if (!bind_addr_success)
178     {
179         error.SetErrorString("Failed to bind port");
180         return error;
181     }
182
183     int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength());
184     if (err != -1)
185         err = ::listen (GetNativeSocket(), backlog);
186
187     if (err == -1)
188         SetLastError (error);
189
190     return error;
191 }
192
193 Error
194 TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket)
195 {
196     Error error;
197     std::string host_str;
198     std::string port_str;
199     int32_t port;
200     if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
201         return error;
202
203     const sa_family_t family = kDomain;
204     const int socktype = kType;
205     const int protocol = IPPROTO_TCP;
206     SocketAddress listen_addr;
207     if (host_str.empty())
208         listen_addr.SetToLocalhost(family, port);
209     else if (host_str.compare("*") == 0)
210         listen_addr.SetToAnyAddress(family, port);
211     else
212     {
213         if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
214         {
215             error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
216             return error;
217         }
218     }
219
220     bool accept_connection = false;
221     std::unique_ptr<TCPSocket> accepted_socket;
222
223     // Loop until we are happy with our connection
224     while (!accept_connection)
225     {
226         struct sockaddr_in accept_addr;
227         ::memset (&accept_addr, 0, sizeof accept_addr);
228 #if !(defined (__linux__) || defined(_WIN32))
229         accept_addr.sin_len = sizeof accept_addr;
230 #endif
231         socklen_t accept_addr_len = sizeof accept_addr;
232
233         int sock = AcceptSocket (GetNativeSocket(),
234                                  (struct sockaddr *)&accept_addr,
235                                  &accept_addr_len,
236                                  child_processes_inherit,
237                                  error);
238
239         if (error.Fail())
240             break;
241
242         bool is_same_addr = true;
243 #if !(defined(__linux__) || (defined(_WIN32)))
244         is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
245 #endif
246         if (is_same_addr)
247             is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
248
249         if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
250         {
251             accept_connection = true;
252             accepted_socket.reset(new TCPSocket(sock, true));
253         }
254         else
255         {
256             const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
257             const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
258             ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
259                         accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
260                         listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
261             accepted_socket.reset();
262         }
263     }
264
265     if (!accepted_socket)
266         return error;
267
268     // Keep our TCP packets coming without any delays.
269     accepted_socket->SetOptionNoDelay();
270     error.Clear();
271     conn_socket = accepted_socket.release();
272     return error;
273 }
274
275 int
276 TCPSocket::SetOptionNoDelay()
277 {
278     return SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
279 }
280
281 int
282 TCPSocket::SetOptionReuseAddress()
283 {
284     return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
285 }